如何在语法中使用空格?

时间:2019-05-17 10:51:30

标签: parsing grammar bison context-free-grammar

我想为LISP的简化版本创建解析器/词法分析器。这是野牛/ 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

components_list : /*nothing*/
     | components_list component

 component : OP STR NUM CP

该字符串符合语法("f" 1) ("f"1)( "f" 1)( "f" 1 )。但是表达式("f"1)对我来说似乎很糟糕,我决定在语法中添加明显的定界符(WHITESPACE类标记[ \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_wspace中添加components_list的用法)。

所以我的基本问题是如何在语法中使用定界符/空格?我看了python(https://github.com/python/cpython/blob/master/Grammar/Grammar)的语法,但似乎没有提及空格表达式/令牌。这是次要的报价:

  

stmt:simple_stmt | compound_stmt

     

simple_stmt:small_stmt(';'small_stmt)* [';'] NEWLINE

     

small_stmt:(expr_stmt | del_stmt | pass_stmt | flow_stmt |                import_stmt | global_stmt | nonlocal_stmt | assert_stmt)

     

expr_stmt:testlist_star_expr(annassign | augassign(yield_expr | testlist)|                        [('='(yield_expr | testlist_star_expr))+ [TYPE_COMMENT]])

1 个答案:

答案 0 :(得分:1)

我不知道的任何修补程序(或通常说来的编程语言)都没有强迫您在这样的令牌之间放置空格。例如,(display"hello")(format t"~d"42)之类的东西分别在Scheme和Common Lisp中可以正常工作。因此,您尝试做的事情通常不会完成,我建议您不要这样做。

也就是说,如果您确实想在某些令牌之间强制使用空格,则两个选择是要么继续做您正在做的事情,要么为无效令牌定义一个规则,该规则与要禁止的任何令牌序列匹配。像这样:

[0-9]+ {return NUM;}
["][^"]*["] { return STR; }
(["][^"]*["]|[0-9]+){2,} { return INVALID_TOKEN; }

因此,只要多个字符串或数字彼此相邻出现而在两者之间没有任何东西,就会生成INVALID_TOKEN。当您添加不想彼此相邻的更多类型的令牌(例如标识符)时,这种模式将变得越来越复杂。

PS:只允许字符串中的字母是非常不寻常的,这就是为什么我在上面更改了字符串文字的正则表达式的原因。您可能需要进一步调整它,以允许在字符串中使用转义的双引号。