使用 Jison 将命令列表转换为对象数组



我正在尝试使用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的"右侧"有关,但除此之外,我很迷茫。

任何帮助将不胜感激!

我正在附加一个语法,可以满足您的要求。显著的变化是:

  1. LINE_END具有正则表达式n+|$,也匹配输出的结尾。

  2. 我添加了一个start制作,其作用只是返回最终结果。

  3. 重写了expression生产以生成阵列。我还从e LINE_END规则中删除了{return $1},因为这会导致解析器过早返回。

  4. 修改了expressions生产以连接数组。

对于expressionexpressions作品,我在那里使用了规则的速记语法。例如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的某些功能。

相关内容

  • 没有找到相关文章

最新更新