如何通过查看前一个标记来告诉语言解析器扫描器字符串是文字而不是标识符

How to tell a language parser scanner that a string is a literal and not an identifier by looking at the previous token

我正在编写一个查询语言解析器,我目前正面临一个我在编程语言编译器中没有遇到过的问题。

我有以下查询:

status=acknowledged

我希望 status 是一个变量标识符,acknowledged 是一个字符串文字。确定这一点的唯一方法是查看两者之间的 = 运算符。

从理论上讲,扫描器应该能够 return 一个新的标记而不用查看以前的标记,但如果是这样的话,您将如何区分标识符和字符串文字? 请记住,我不能只在 acknowledged 字符串周围添加双引号,因为我需要使用已经存在的查询语言并且不允许对其进行任何更改。

我是否应该只跟踪扫描仪内的前 N ​​个令牌并采取相应行动?

如果我有这样的事情,事情会变得更加混乱:

status=acknowledged&visibility=all

在这种情况下,=& 都是运算符,所以我不能只说如果我当前正在解析的标记之前的标记是运算符,我应该将其视为字符串字面量。

你需要问自己的问题是"Does my parser need to know whether acknowledged is a variable identifier or a string literal?"

我要大胆地建议答案是 "No, it doesn't"。您可以 解析 status=acknowledged&visibility=all 这样的表达式,而无需了解 statusacknowledged(或 visibilityall)除此之外,它们是操作数。此类操作数的可能词法类别可能是 "bare words"(该术语来自 Perl)或 "atoms" (Lisp)。

当然,在某些时候你会想弄清楚这些标记 的意思(根据定义,这是一个语义问题),到那时它们中的一些会被解析为 "variable name",其他人被解析为(未引用)"string literal"。例如,如果您的 = 运算符坚持其左侧操作数是变量名,而其右侧运算符是文字,则您可以在自上而下遍历解析过程中轻松地进行适当的转换树。我很确定这是大多数类似解析器所采用的方法。

根据关注点分离原则,语言处理器中的每个组件都应尽可能将自己限制在拼图的单个部分。尽量避免过早进行分析的诱惑,这样可以更轻松地推迟到适当的未来阶段。如果您按照这种模式工作,您会发现所有的逻辑都更加简单。