我在这里找到了 Lemon 的 Lua 5.1 语法(页末的清单 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: "'".
缺少什么?
这看起来像我几年前的作品。它旨在用于我创建但不再维护的柠檬的修改版本,它在Lua中生成了一个解析器。
为了将其与开箱即用的柠檬解析器一起使用,您必须将引用文本的所有实例替换为命名标记。请参阅柠檬文档中有关终端和非终端的部分。(在您链接的页面中有一个关于此的注释。
与 yacc/bison 不同,lemon 不需要您声明令牌名称,因为此类名称必须以大写字母开头。与 yacc/bison 一样,lemon 会生成一个头文件,其中包含这些名称的定义,您可以在扫描仪实现中#include
这些文件。(使用 flex 为 lemon 解析器生成扫描程序很容易,但您应该仔细阅读 lemon 文档;lemon 解析器由扫描程序调用,而不是调用扫描程序。
有几个柠檬特征在 yacc/bison 中不存在,这将使将这种语法转换为 yacc/bison 变得复杂:
-
柠檬中的
|
符号没有记录,与yacc/bison中使用|
不同;它只能用于创建替代终端令牌的列表。在 yacc/bison 中,您可以创建此形式的非终端,但非终端不参与优先规则;在柠檬中,替代方案列表是一个"多终端",它不会干扰优先规则。因此,在 yacc/bison 中,您必须为每个替代终端使用令牌替代品复制生产。另一种 yacc/bison 方法是对组中的所有替代方案使用单个词汇标记,通过它们的语义值来区分它们,这可能是一个enum
.这对于操作员终端来说效果很好,但不适用于像','|';'
这样的替代方案,因为这些在整个语法中不一致。 -
没有等价物的
%fallback
,也没有简单的解决方法。