我正在尝试使用Jison,它是解析器生成器Bison的JS端口。我的目标是转换此输入:
foo(10)
bar()
foo(28)
baz(28)
进入这个:
[
{ func: 'foo', arg: 10 },
{ func: 'bar' },
{ func: 'foo', arg: 28 },
{ func: 'baz', arg: 28 }
]
这是我的野牛文件:
%lex
%%
[0-9]+b return 'INTEGER'
( return 'OPEN_PAREN'
) return 'CLOSE_PAREN'
[w]+s*(?=() return 'FUNC_NAME'
n+ return 'LINE_END'
/lex
%%
expressions
: expressions expression
| expression
;
expression
: LINE_END
| e LINE_END
{return $1}
;
e
: FUNC_NAME OPEN_PAREN INTEGER CLOSE_PAREN
{$$ = { func: $1, arg: $3 };}
| FUNC_NAME OPEN_PAREN CLOSE_PAREN
{$$ = { func: $1 };}
;
生成的解析器的输出为 { func: 'foo', arg: 10 }
。换句话说,它只返回第一个语句中解析的对象,而忽略其余的对象。
我知道我的问题与语义值和expression
的"右侧"有关,但除此之外,我很迷茫。
任何帮助将不胜感激!
我正在附加一个语法,可以满足您的要求。显著的变化是:
-
LINE_END
具有正则表达式n+|$
,也匹配输出的结尾。 -
我添加了一个
start
制作,其作用只是返回最终结果。 -
重写了
expression
生产以生成阵列。我还从e LINE_END
规则中删除了{return $1}
,因为这会导致解析器过早返回。 -
修改了
expressions
生产以连接数组。
对于expression
和expressions
作品,我在那里使用了规则的速记语法。例如expression -> [$1]
等效于expression { $$ = [$1] }
。
这是语法:
%lex
%%
[0-9]+b return 'INTEGER'
( return 'OPEN_PAREN'
) return 'CLOSE_PAREN'
[w]+s*(?=() return 'FUNC_NAME'
n+|$ return 'LINE_END'
/lex
%%
start:
expressions
{ return $1 }
;
expressions
: expressions expression -> $1.concat($2)
| expression
;
expression
: LINE_END -> []
| e LINE_END -> [$1]
;
e
: FUNC_NAME OPEN_PAREN INTEGER CLOSE_PAREN
{$$ = { func: $1, arg: $3 };}
| FUNC_NAME OPEN_PAREN CLOSE_PAREN
{$$ = { func: $1 };}
;
题外话:吉森不是野牛的港口。它是一个解析器生成器,其功能受到Bison的强烈启发,但它具有Bison所没有的功能,并且Jison不支持Bison的某些功能。