我正在使用CL-Lex来实现词法分析器(作为CL-YACC的输入),我的语言有几个关键词,如“let”和“in”。然而,虽然词法分析器识别出这样的关键词,但它确实太多了。当它找到诸如“init”之类的单词时,它将第一个标记返回为IN,而它应该为“init”字返回一个“CONST”标记。
这是词法分析器的简单版本:
(define-string-lexer lexer
(...)
("in" (return (values :in $@)))
("[a-z]([a-z]|[A-Z]|\_)" (return (values :const $@))))
如何强制词法分析器完全读取整个单词,直到出现一些空格?
答案 0 :(得分:8)
这既是对Kaz的错误的纠正,也是对OP的信任投票。
在他最初的回答中,Kaz说明了Unix lex
优先顺序完全落后。来自lex
文档:
Lex可以处理模棱两可的规范。当多个表达式可以 匹配当前输入,Lex选择如下:
最长匹配是首选。
- 醇>
在符合相同数量字符的规则中,给出了规则 首先是首选。
此外,Kaz批评OP使用Perl-regex字边界匹配的解决方案是错误的。碰巧的是,你被允许(没有折磨内疚)来匹配词法生成器支持的任何方式的单词。 CL-LEX使用Perl正则表达式,它使用\b
作为方便的语法来处理更加繁琐的lex
近似值:
%{
#include <stdio.h>
%}
WC [A-Za-z']
NW [^A-Za-z']
%start INW NIW
{WC} { BEGIN INW; REJECT; }
{NW} { BEGIN NIW; REJECT; }
<INW>a { printf("'a' in wordn"); }
<NIW>a { printf("'a' not in wordn"); }
在所有条件相同的情况下,找到一种明确匹配他的话的方法可能比替代方案更好。
尽管Kaz想要打他,但OP正确地回答了他自己的问题,提出了一个利用他选择的词法分析器灵活性的解决方案。
答案 1 :(得分:1)
上面的示例词法分析器有两个规则,两个规则都匹配正好两个字符的序列。而且,它们有共同的匹配(第二种匹配的语言是第一种的严格超集)。
在经典的Unix lex
中,如果两个规则都匹配相同的输入长度,则优先级将在规范中首先出现。否则,最长的匹配将占主导地位。
(虽然没有RTFM,但我不能说这就是CL-LEX中发生的事情,它确实对这种情况下发生的事情做出了合理的假设。)
看起来你缺少一个正则表达式Kleene运算符来匹配第二个规则中的较长令牌。