我正在编写一个小程序,需要预处理一些输入到另一个程序的数据文件。因此,我无法更改输入文件的格式,并且遇到了问题。
我正在使用一种没有此类文件库的语言,我不介意练习,所以我计划手动实现词法分析器和解析器。我想基于this粗略地实现一个Lexer,这是一个相当简单的设计。
我需要解释的输入文件有一个包含化学反应的部分。反应每一侧的不同化学物质用“+”符号分隔,但物种名称中也可以有+字符(象征电荷)。例如:
N2+O2=>NO+NO
N2++O2-=>NO+NO
N2+ + O2 => NO + NO
都是有效的,词法分析器输出的标记应该是
'N2' '+' 'O2' '=>' 'NO' '+' 'NO'
'N2+' '+' 'O2-' '=>' 'NO' '+' 'NO'
'N2+' '+' 'O2-' '=>' 'NO' '+' 'NO'
(注意最后两个是相同的)。为了简单起见,我想避免在词法分析器中向前看。问题是词法分析器将开始读取上述任何输入,但是当它到达第3个字符(第一个'+')时,它将无法知道它是否是物种名称的一部分或者它是否是反应物之间的分隔物。
为了解决这个问题,我想我会将其分开,以便上面的第二个和第三个例子输出:
'N2' '+' '+' 'O2-' '=>' 'NO' '+' 'NO'
然后解析器将简单地使用上下文,意识到连续的两个“+”标记意味着第一个是前一个物种名称的一部分,并且将正确处理上述所有三种情况。这个问题是现在想象我尝试lex / parse
N2 + + O2- => NO + NO
(注意'N2'和第一个'+'之间的空格)。这是无效的语法,但是我刚刚描述的词法分析器将输出与第二个和第三个示例完全相同的令牌输出,并且我的解析器将无法捕获错误。
我认为可能的解决方案:
由于我对这种编程很陌生,所以我希望有人可以评论我提出的解决方案(或建议另一种解决方案)。我对第一个解决方案的主要保留意见是,我只是不知道在前瞻中实施词法分析器有多复杂。
答案 0 :(得分:1)
您没有提及您的实现语言,但输入语法与您概述的语法相比较简单,我不认为按照以下伪代码的方式使用逻辑是不合理的。
string GetToken()
{
string token = GetAlphaNumeric(); // assumed to ignore (eat) white-space
var ch = GetChar(); // assumed to ignore (eat) white-space
if (ch == '+')
{
var ch2 = GetChar();
if (ch2 == '+')
token += '+';
else
PutChar(ch2);
}
PutChar(ch);
return token;
}