這一章,我們將實現(xiàn)形如"1+12+123-123"這樣連續(xù)的多位數(shù)加減法實現(xiàn),為此,我們需要一點點編譯原理。
語法圖與語法分析
對于上述表達(dá)式,我們可以構(gòu)建一個簡單的語法圖

lsbasi_part3_syntax_diagram.png
對于這個語法圖,類似以下輸入都是合法的:
- 1
- 1+1
- 1 + 23 - 4
對于不滿足這個語法圖的輸入,我們輸出"syntax error",相信這對任何程序員來說都是無比熟悉的東西了。
下一步,我們對輸入的字符串進(jìn)行語法分析,將輸入的字符串分解成一個個的Token,同時檢測其是否滿足語法圖的條件,首先實現(xiàn)一個term函數(shù)來檢測Token是否為term:
void Interpreter::term()
{
eat(TokenType::TT_INTEGER);
}
第一步,我們只是簡單調(diào)用eat函數(shù),這樣當(dāng)Token類型不是TT_INTEGER時,eat函數(shù)會拋出錯誤。
然后在expr中實現(xiàn)語法圖的合法性檢測:
void Interpreter::expr()
{
currentTokenPtr = getNextTokenPtr();
term();
while (currentTokenPtr->getType() == TokenType::TT_MINUS ||
currentTokenPtr->getType() == TokenType::TT_PLUS)
{
TokenPtr tokenPtr = currentTokenPtr;
if (tokenPtr->getType() == TokenType::TT_MINUS ||
tokenPtr->getType() == TokenType::TT_PLUS)
{
eat(tokenPtr->getType());
term();
}
}
}
至此,我們實現(xiàn)了一個簡單的語法分析器,但是它只能檢測語法是否合法,并不能輸出結(jié)果,接下來我們向里面添加具體的計算處理:
TokenValue Interpreter::term()
{
TokenPtr tokenPtr = currentTokenPtr;
eat(TokenType::TT_INTEGER);
return tokenPtr->getValue();
}
int Interpreter::expr()
{
currentTokenPtr = getNextTokenPtr();
int leftValue = get<int>(term());
while (currentTokenPtr->getType() == TokenType::TT_MINUS ||
currentTokenPtr->getType() == TokenType::TT_PLUS)
{
TokenPtr tokenPtr = currentTokenPtr;
if (tokenPtr->getType() == TokenType::TT_MINUS ||
tokenPtr->getType() == TokenType::TT_PLUS)
{
TokenType opTokenType = tokenPtr->getType();
eat(opTokenType);
int rightValue = get<int>(term());
switch (opTokenType)
{
case TokenType::TT_MINUS:
leftValue -= rightValue;
break;
case TokenType::TT_PLUS:
leftValue += rightValue;
break;
default:
raiseError();
break;
}
}
}
return leftValue;
}
好了,我們的多位數(shù)加減法解釋器又支持了更多特性,congrats!
當(dāng)然真正的編程語言的語法圖跟語法分析要遠(yuǎn)遠(yuǎn)比這個復(fù)雜,我們以后再慢慢迭代,只是通過這個例子了解一下編譯原理的第一步。