Parsing 如何在语法中使用空格?
我想为简化版的LISP创建解析器/词法分析器。以下是bison/lexer规格:Parsing 如何在语法中使用空格?,parsing,grammar,bison,context-free-grammar,Parsing,Grammar,Bison,Context Free Grammar,我想为简化版的LISP创建解析器/词法分析器。以下是bison/lexer规格: /* Lexer file */ "(" {return OP;} ")" {return CP;} [0-9]+ {return NUM;} ["][a-zA-Z]*["] { return STR; } [ \n\r\f] { /*do nothing*/} . {return INVALID_TOKEN;} /* Bison file */ start_expr: components_list
/* Lexer file */
"(" {return OP;}
")" {return CP;}
[0-9]+ {return NUM;}
["][a-zA-Z]*["] { return STR; }
[ \n\r\f] { /*do nothing*/}
. {return INVALID_TOKEN;}
/* Bison file */
start_expr: components_list
components_list : /*nothing*/
| components_list component
component : OP STR NUM CP
这样的字符串符合语法(“f”1)(“f”1)(“f”1)(“f”1)
。但是表达式(“f”1)
对我来说非常糟糕,我决定在语法中添加明确的分隔符(使用空格标记[\n\r\f]+
)。诸如此类:
opt_wspace : /*nothing*/
| WHITESPACE
start_expr: components_list
components_list : /*nothing*/
| components_list component
component : OP opt_wspace STR WHITESPACE NUM opt_wspace CP
但是现在(对我来说)语法看起来很糟糕,但是类似(“f”1)
的表达式是不允许的。另一个时刻是,现在我很容易犯语法错误。例如,这样的表达式将不会被解析(“f”1)(“f”1)
(我忘了在组件列表中添加opt\u wspace
的用法)
所以我的基本问题是如何在语法中使用分隔符/空格?我查看了python()的语法,但它似乎没有提到空格表达式/标记。下面是一段小引语:
stmt:简单的|复合的|stmt
简单语法:小语法(“;”小语法)*[“;”]换行
小型:(expr|stmt | del|stmt | pass|stmt | flow|stmt)|
导入|全局|非本地|断言|
expr|stmt:testlist_star|expr(annassign|augsign(yield|expr|testlist)|
[('='(yield|expr | testlist_star_expr))+[TYPE_COMMENT]]
我所知道的所有Lisp(或者真正的编程语言)都不会强迫您在标记之间放置空格。例如,(显示“hello”)
或(格式t“~d”42)
分别在Scheme和Common Lisp中工作良好。所以你尝试去做的事情并不常见,我建议你不要去做
这就是说,如果您确实希望在某些令牌之间强制使用空格,那么您的两个选项是要么继续执行您正在执行的操作,要么为无效令牌定义一个规则,该规则与您想要禁止的任何令牌序列相匹配。大概是这样的:
[0-9]+ {return NUM;}
["][^"]*["] { return STR; }
(["][^"]*["]|[0-9]+){2,} { return INVALID_TOKEN; }
因此,每当多个字符串或数字相邻出现且中间没有任何内容时,就会生成无效的\u标记。当您添加更多类型的令牌时,这种模式将变得越来越复杂,您不希望这些令牌彼此相邻(例如标识符)
PS:只允许字符串中的字母是非常不寻常的,这就是为什么我在上面更改了字符串文本的正则表达式。您可能需要进一步调整它,以允许在字符串中使用转义双引号。我不同意您的看法。例如,在racket
中,你不能写这样的东西(structаa([x:Real])
,只有(structаa([x:Real]))
@LmTinyToon,这是因为x:Real
是一个有效的标识符。是的,我同意你的看法。