你如何处理Lex中的关键字?

时间:2018-04-02 09:43:34

标签: parsing yacc lex

假设您的语言允许这样生成:optional optional = 42,其中第一个“可选”是关键字,第二个“可选”是标识符。

一方面,我希望有一个像optional { return OPTIONAL; }这样的Lex规则,以后会在YACC中使用,例如:

optional : OPTIONAL identifier '=' expression ;

如果我然后将identifier定义为:

identifier : OPTIONAL | FIXED32 | FIXED64 | ... /* couple dozens of keywords */ 
    | IDENTIFIER ;

它只是感觉很糟糕...此外,我需要两种标识符,一种用于何时允许关键字作为标识符,另一种用于何时不是... ...

有解决这个问题的惯用方法吗?

3 个答案:

答案 0 :(得分:1)

  

有解决这个问题的惯用方法吗?

除了你已经找到的解决方案,没有。半保留关键字绝对不是lex / yacc语法的预期用例。

柠檬解析器生成器有一个为这样的情况设计的回退声明,但据我所知,这个有用的功能从未被添加到野牛。

您可以使用GLR语法来避免必须找出DECLARE @a bigint; SELECT @a = MAX(ABC.milisecDateTimeBigInt) FROM ABC WHERE ABC.ID = 1; SELECT * FROM XYZ WHERE XYZ.milisecDateTimeBigInt = @a 的所有不同子集。但当然会有性能损失。

答案 1 :(得分:1)

你已经发现了在lex / yacc中处理这个问题最常用的方法,虽然不是很好,但也不错。通常,您调用的规则与标识符或(一组)关键字whateverName匹配,并且您可能拥有多个关键字 - 因为不同的上下文可能具有不同的关键字集,它们可以作为名称接受。

如果你在易于识别的地方(例如在行的开头)只识别出这样的关键字,那么可能有用的另一种方法是使用lex启动状态,以便只返回一个KEYWORD标记,如果关键字在这种背景下。在任何其他上下文中,关键字将仅作为标识符标记返回。您甚至可以使用yacc操作为某些复杂的上下文设置词法分析器状态,但是您需要知道解析器可能执行的一个令牌词法分析器前瞻(规则可能直到在操作已经读取后的令牌之后才会运行)。

答案 2 :(得分:1)

在这种情况下,没有保留关键字。几种编程语言允许这样做:PL / I,FORTRAN。这不是词法分析器的问题,因为词法分析器应该始终知道哪些IDENTIFIER是关键字。这是解析器问题。它通常在语言规范中引起太多歧义,并且解析成为噩梦。语法将具有以下内容:

标识符:关键字|标识符;

关键字:可选| FIXED32 | FIXED64 | ...;

如果语法没有冲突,那么您就可以了。如果存在冲突,则需要功能更强大的解析器生成器,例如LR(k)或GLR。