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

Using Jison to convert a list of commands into an array of objects

我正在尝试使用 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 }
  ;

e
  : FUNC_NAME OPEN_PAREN INTEGER CLOSE_PAREN
    {$$ = { func: , arg:  };}

  | FUNC_NAME OPEN_PAREN CLOSE_PAREN
    {$$ = { func:  };}
  ;

生成的解析器的输出是 { func: 'foo', arg: 10 }。换句话说,它只 returns 第一个语句中的已解析对象而忽略其余部分。

我知道我的问题与语义值和 expression 的 "right side" 有关,但除此之外我很迷茫。

任何帮助将不胜感激!

我正在附加一个语法来满足您的要求。显着变化是:

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

  2. 我添加了一个start制作,它的作用只是return最终结果。

  3. 重写了 expression 产生式以产生数组。我还从 e LINE_END 规则中删除了 {return },因为这会导致解析器过早地 return。

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

对于 expressionexpressions 作品,我在那里的规则使用了 shorthand 语法。例如 expression -> [] 等同于 expression { $$ = [] }.

语法如下:

%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  }
  ;

expressions
  : expressions expression -> .concat()
  | expression
  ;

expression
  : LINE_END -> []
  | e LINE_END -> []
  ;

e 
  : FUNC_NAME OPEN_PAREN INTEGER CLOSE_PAREN
    {$$ = { func: , arg:  };}

  | FUNC_NAME OPEN_PAREN CLOSE_PAREN
    {$$ = { func:  };}
  ;

旁白:Jison 不是 Bison 的港口。它是一个解析器生成器,其功能受到 Bison 的强烈启发,但它具有 Bison 没有的功能,并且 Jison 不支持 Bison 的某些功能。