c++ - 如何使用Lua5.1 柠檬语法?

标签 c++ parsing lua lemon

我找到了 Lemon 的 Lua 5.1 语法 here (页尾的 list 1):

%fallback  OPEN '(' .

chunk      ::= block .

semi       ::= ';' .
semi       ::= .

block      ::= scope statlist .
block      ::= scope statlist laststat semi .
ublock     ::= block 'until' exp .

scope      ::= .
scope      ::= scope statlist binding semi.

statlist   ::= .
statlist   ::= statlist stat semi .

stat       ::= 'do' block 'end' .
stat       ::= 'while' exp 'do' block 'end' .
stat       ::= repetition 'do' block 'end' .
stat       ::= 'repeat' ublock .
stat       ::= 'if' conds 'end' .
stat       ::= 'function' funcname funcbody .
stat       ::= setlist '=' explist1 .
stat       ::= functioncall .

repetition ::= 'for' NAME '=' explist23 .
repetition ::= 'for' namelist 'in' explist1 .

conds      ::= condlist .
conds      ::= condlist 'else' block .
condlist   ::= cond .
condlist   ::= condlist 'elseif' cond .
cond       ::= exp 'then' block .

laststat   ::= 'break' .
laststat   ::= 'return' .
laststat   ::= 'return' explist1 .

binding    ::= 'local' namelist .
binding    ::= 'local' namelist '=' explist1 .
binding    ::= 'local' 'function' NAME funcbody .

funcname   ::= dottedname .
funcname   ::= dottedname ':' NAME .

dottedname ::= NAME .
dottedname ::= dottedname '.' NAME .

namelist   ::= NAME .
namelist   ::= namelist ',' NAME .

explist1   ::= exp .
explist1   ::= explist1 ',' exp .
explist23  ::= exp ',' exp .
explist23  ::= exp ',' exp ',' exp .

%left      'or' .
%left      'and' .
%left      '<' '<=' '>' '>=' '==' '~=' .
%right     '..' .
%left      '+' '-' .
%left      '*' '/' '%' .
%right     'not' '#' .
%right     '^' .

exp        ::= 'nil'|'true'|'false'|NUMBER|STRING|'...' .
exp        ::= function .
exp        ::= prefixexp .
exp        ::= tableconstructor .
exp        ::= 'not'|'#'|'-' exp .         ['not']
exp        ::= exp 'or' exp .
exp        ::= exp 'and' exp .
exp        ::= exp '<'|'<='|'>'|'>='|'=='|'~=' exp .
exp        ::= exp '..' exp .
exp        ::= exp '+'|'-' exp .
exp        ::= exp '*'|'/'|'%' exp .
exp        ::= exp '^' exp .

setlist    ::= var .
setlist    ::= setlist ',' var .

var        ::= NAME .
var        ::= prefixexp '[' exp ']' .
var        ::= prefixexp '.' NAME .

prefixexp  ::= var .
prefixexp  ::= functioncall .
prefixexp  ::= OPEN exp ')' .

functioncall ::= prefixexp args .
functioncall ::= prefixexp ':' NAME args .

args        ::= '(' ')' .
args        ::= '(' explist1 ')' .
args        ::= tableconstructor .
args        ::= STRING .

function    ::= 'function' funcbody .

funcbody    ::= params block 'end' .

params      ::= '(' parlist ')' .

parlist     ::= .
parlist     ::= namelist .
parlist     ::= '...' .
parlist     ::= namelist ',' '...' .

tableconstructor ::= '{' '}' .
tableconstructor ::= '{' fieldlist '}' .
tableconstructor ::= '{' fieldlist ','|';' '}' .

fieldlist   ::= field .
fieldlist   ::= fieldlist ','|';' field .

field       ::= exp .
field       ::= NAME '=' exp .
field       ::= '[' exp ']' '=' exp .

我尝试用 lemon -c lua51.y 编译它,但出现了很多错误:

lua51.y:3: %fallback argument "'" should be a token
lua51.y:3: %fallback argument "(" should be a token
lua51.y:3: %fallback argument "'" should be a token
lua51.y:7: Illegal character on RHS of rule: "'".
lua51.y:12: Illegal character on RHS of rule: "'".
lua51.y:20: Illegal character on RHS of rule: "'".
lua51.y:21: Illegal character on RHS of rule: "'".
lua51.y:22: Illegal character on RHS of rule: "'".
lua51.y:23: Illegal character on RHS of rule: "'".
lua51.y:24: Illegal character on RHS of rule: "'".
lua51.y:25: Illegal character on RHS of rule: "'".
lua51.y:26: Illegal character on RHS of rule: "'".
lua51.y:29: Illegal character on RHS of rule: "'".
lua51.y:30: Illegal character on RHS of rule: "'".
lua51.y:33: Illegal character on RHS of rule: "'".
lua51.y:35: Illegal character on RHS of rule: "'".
lua51.y:36: Illegal character on RHS of rule: "'".
lua51.y:38: Illegal character on RHS of rule: "'".
lua51.y:39: Illegal character on RHS of rule: "'".
lua51.y:40: Illegal character on RHS of rule: "'".
lua51.y:42: Illegal character on RHS of rule: "'".
lua51.y:43: Illegal character on RHS of rule: "'".
lua51.y:44: Illegal character on RHS of rule: "'".
lua51.y:47: Illegal character on RHS of rule: "'".
lua51.y:50: Illegal character on RHS of rule: "'".
lua51.y:50: Token "'" should be either "%" or a nonterminal name.
lua51.y:50: Token "NAME" should be either "%" or a nonterminal name.
lua51.y:50: Token "." should be either "%" or a nonterminal name.
lua51.y:53: Illegal character on RHS of rule: "'".
lua51.y:56: Illegal character on RHS of rule: "'".
lua51.y:57: Illegal character on RHS of rule: "'".
lua51.y:58: Illegal character on RHS of rule: "'".
lua51.y:60: Can't assign a precedence to "'".
lua51.y:60: Can't assign a precedence to "or".
lua51.y:60: Can't assign a precedence to "'".
lua51.y:61: Can't assign a precedence to "'".
lua51.y:61: Can't assign a precedence to "and".
lua51.y:61: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to "<".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to "<".
lua51.y:62: Can't assign a precedence to "=".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to ">".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to ">".
lua51.y:62: Can't assign a precedence to "=".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to "=".
lua51.y:62: Can't assign a precedence to "=".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:62: Can't assign a precedence to "~".
lua51.y:62: Can't assign a precedence to "=".
lua51.y:62: Can't assign a precedence to "'".
lua51.y:63: Can't assign a precedence to "'".
lua51.y:63: Token "." should be either "%" or a nonterminal name.
lua51.y:63: Token "'" should be either "%" or a nonterminal name.
lua51.y:63: Token "." should be either "%" or a nonterminal name.
lua51.y:64: Can't assign a precedence to "'".
lua51.y:64: Can't assign a precedence to "+".
lua51.y:64: Can't assign a precedence to "'".
lua51.y:64: Can't assign a precedence to "'".
lua51.y:64: Can't assign a precedence to "-".
lua51.y:64: Can't assign a precedence to "'".
lua51.y:65: Can't assign a precedence to "'".
lua51.y:65: Can't assign a precedence to "*".
lua51.y:65: Can't assign a precedence to "'".
lua51.y:65: Can't assign a precedence to "'".
lua51.y:65: Can't assign a precedence to "/".
lua51.y:65: Can't assign a precedence to "'".
lua51.y:65: Can't assign a precedence to "'".
lua51.y:65: Can't assign a precedence to "%".
lua51.y:65: Can't assign a precedence to "'".
lua51.y:66: Can't assign a precedence to "'".
lua51.y:66: Can't assign a precedence to "not".
lua51.y:66: Can't assign a precedence to "'".
lua51.y:66: Can't assign a precedence to "'".
lua51.y:66: Can't assign a precedence to "#".
lua51.y:66: Can't assign a precedence to "'".
lua51.y:67: Can't assign a precedence to "'".
lua51.y:67: Can't assign a precedence to "^".
lua51.y:67: Can't assign a precedence to "'".
lua51.y:69: Illegal character on RHS of rule: "'".
lua51.y:69: Token "." should be either "%" or a nonterminal name.
lua51.y:69: Token "." should be either "%" or a nonterminal name.
lua51.y:69: Token "'" should be either "%" or a nonterminal name.
lua51.y:69: Token "." should be either "%" or a nonterminal name.
lua51.y:73: Illegal character on RHS of rule: "'".
lua51.y:73: The precedence symbol must be a terminal.
lua51.y:73: Missing "]" on precedence mark.
lua51.y:73: Token "'" should be either "%" or a nonterminal name.
lua51.y:73: Token "]" should be either "%" or a nonterminal name.
lua51.y:74: Illegal character on RHS of rule: "'".
lua51.y:75: Illegal character on RHS of rule: "'".
lua51.y:76: Illegal character on RHS of rule: "'".
lua51.y:77: Illegal character on RHS of rule: "'".
lua51.y:77: Token "." should be either "%" or a nonterminal name.
lua51.y:77: Token "'" should be either "%" or a nonterminal name.
lua51.y:77: Expected to see a ":" following the LHS symbol "exp".
lua51.y:79: Illegal character on RHS of rule: "'".
lua51.y:79: Illegal declaration keyword: "'".
lua51.y:80: Illegal character on RHS of rule: "'".
lua51.y:83: Illegal character on RHS of rule: "'".
lua51.y:86: Illegal character on RHS of rule: "'".
lua51.y:87: Illegal character on RHS of rule: "'".
lua51.y:87: Token "'" should be either "%" or a nonterminal name.
lua51.y:87: Token "NAME" should be either "%" or a nonterminal name.
lua51.y:87: Token "." should be either "%" or a nonterminal name.
lua51.y:91: Illegal character on RHS of rule: "'".
lua51.y:94: Illegal character on RHS of rule: "'".
lua51.y:96: Illegal character on RHS of rule: "'".
lua51.y:97: Illegal character on RHS of rule: "'".
lua51.y:101: Illegal character on RHS of rule: "'".
lua51.y:103: Illegal character on RHS of rule: "'".
lua51.y:105: Illegal character on RHS of rule: "'".
lua51.y:109: Illegal character on RHS of rule: "'".
lua51.y:109: Token "." should be either "%" or a nonterminal name.
lua51.y:109: Token "." should be either "%" or a nonterminal name.
lua51.y:109: Token "'" should be either "%" or a nonterminal name.
lua51.y:109: Token "." should be either "%" or a nonterminal name.
lua51.y:110: Illegal character on RHS of rule: "'".
lua51.y:110: Token "." should be either "%" or a nonterminal name.
lua51.y:110: Token "." should be either "%" or a nonterminal name.
lua51.y:110: Token "'" should be either "%" or a nonterminal name.
lua51.y:110: Token "." should be either "%" or a nonterminal name.
lua51.y:112: Illegal character on RHS of rule: "'".
lua51.y:113: Illegal character on RHS of rule: "'".
lua51.y:114: Illegal character on RHS of rule: "'".
lua51.y:117: Illegal character on RHS of rule: "'".
lua51.y:120: Illegal character on RHS of rule: "'".
lua51.y:121: Illegal character on RHS of rule: "'".

缺少什么?

最佳答案

这看起来像我几年前的作品。它适用于我创建但不再维护的 lemon 的修改版本,它在 Lua 中生成了一个解析器。

为了将它与开箱即用的柠檬解析器一起使用,您必须将所有引用文字的实例替换为命名标记。请参阅 lemon documentation 中有关终端和非终端的部分. (在您链接的页面中有关于此的注释。)

与 yacc/bison 不同,lemon 不要求您声明 token 名称,因为此类名称必须以大写字母开头。与 yacc/bison 一样,lemon 将生成一个包含这些名称定义的头文件,您可以在扫描器实现中#include。 (使用 flex 很容易为柠檬解析器生成扫描器,但您应该仔细阅读柠檬文档;柠檬解析器由扫描器调用,而不是调用扫描器。)


有一些柠檬特性在 yacc/bison 中不存在,这会使为 yacc/bison 转换此语法变得复杂:

  • lemon 中的 | 符号没有记录,并且与 yacc/bison 中的 | 的使用不同;它只能用于创建替代终端 token 列表。在 yacc/bison 中,您可以创建这种形式的非终端,但非终端不参与优先规则;在柠檬中,备选方案列表是一个不干扰优先规则的“多终端”。因此,在 yacc/bison 中,您将不得不使用每个替代终端的 token 替代品来复制产品。另一种 yacc/bison 方法是对一组中的所有备选方案使用单个词法标记,通过语义值区分它们,语义值可以是 enum。这适用于运算符(operator)终端,但不适用于 ','|';' 之类的替代方案,因为它们在整个语法中不一致。

  • %fallback 没有等效的 yacc/bison,也没有简单的解决方法。

关于c++ - 如何使用Lua5.1 柠檬语法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50449806/

相关文章:

c++ - 用于查找多数元素的分而治之算法?

c++ - std::invocable 和 std::regular_invocable 概念之间有什么区别?

java - 在 Java 中读取配置

c++ - 如何通过 for 循环从 C/C++ 函数将表的表返回给 Lua

C++:为什么我的函数返回的引用地址与取消引用的指针地址不同?

c++ - 从指针到 const 指针的无效转换

java - 如何在 java 中查找 xml 中缺少的属性

parsing - 如何使用 Parsec 仅在某个范围内解析一串整数?

python - 我怎样才能最好地将这个Python脚本翻译成Lua?

parsing - 如何使用Lua语言从磁盘加载Lua表?