Jison 中并列项的乘法?
Multiplication with juxtaposed terms in Jison?
我最近一直在试验 Jison,我想我会尝试创建一个能够(至少部分地)解析一些数学表达式的语法。
但是,现在我对如何创建一个允许 7a
形式(例如)相乘的规则感到困惑,其中 a
是先前定义的变量。我试图在我的代码中使用 adjmul
来执行此操作,但除非 7
和 a
之间存在 space,否则解析器无法工作。简而言之,如果数字和变量在程序中相邻,我将如何创建一个或多个允许数字和变量相乘的规则?
由于我对像 Jison 这样的解析器一般来说是个新手,所以我也想知道是否有任何方法可以简化我当前的规则。
代码:
/* description: Parses math files. */
/* lexical grammar */
%lex
%%
[\n;] {return 'NL';}
\s+ {/* skip whitespace */}
"=" {return '=';}
[0-9]+("."[0-9]+)?\b {return 'NUMBER';}
"*" {return '*';}
"/" {return '/';}
"-" {return '-';}
"+" {return '+';}
"^" {return '^';}
"(" {return '(';}
")" {return ')';}
[a-zA-Z]+ {return 'ID';}
"," {return ',';}
"|" {return '|';}
"!" {return '!';}
<<EOF>> {return 'EOF';}
/lex
/* operator associations and precedence */
%left '|'
%left ','
%left '+' '-'
%left '*' '/'
%left '^'
%left UMINUS
%left '!'
%start program
%% /* language grammar */
program
: statement 'NL' program
{$$ = "";}
| statement EOF
{$$ = "";}
;
statement
: e
{$$ = ;}
| ID '=' e
{identifiers[] = ;}
;
e
: block '+' block
{$$ = + ;}
| block '-' block
{$$ = - ;}
| block '*' block
{$$ = * ;}
| block '/' block
{$$ = / ;}
| block '^' block
{$$ = Math.pow(, );}
| '-' block %prec UMINUS
{$$ = -;}
| block '!'
{$$ = util.factorial();}
| ID '(' csv ')'
{$$ = identifiers[].apply(null, );}
| ID '(' ')'
{$$ = identifiers[]();}
| ID
{$$ = identifiers[];}
| adjmul
| block
;
block
: term
| NUMBER
{$$ = Number(yytext);}
;
term
: '(' e ')'
{$$ = ;}
;
adjmul
: block term
{$$ = * ;}
| block ID
{$$ = * identifiers[];}
;
数字的正则表达式不正确。它不应该在末尾有 \b。词法分析过程通常应该纯粹是将输入的字符流标记为词法成分,而不考虑这些标记是否出现在有效序列中。构成有效标记序列的是语法规则的任务。与您的代码一样, whitespace 通常也会在词法分析阶段被丢弃,除非它有意义,在这种情况下您也会对其进行标记。因此,流 '123 foo' 或 '123foo' 都会产生 NUMBER 后跟 ID 的标记序列,whitespace 与否通常在表达式中无效。因此,在您的情况下,删除 \b 可能会解决问题,但是您的语法可能会允许“7a”(没有 space)和“7a”与 space。如果您不想允许 space,我很想引入一个由数字和单词组成的新词汇标记,然后您的语法会适当地处理它。这使得 whitespace 的概念不在你的语法范围内。
我最近一直在试验 Jison,我想我会尝试创建一个能够(至少部分地)解析一些数学表达式的语法。
但是,现在我对如何创建一个允许 7a
形式(例如)相乘的规则感到困惑,其中 a
是先前定义的变量。我试图在我的代码中使用 adjmul
来执行此操作,但除非 7
和 a
之间存在 space,否则解析器无法工作。简而言之,如果数字和变量在程序中相邻,我将如何创建一个或多个允许数字和变量相乘的规则?
由于我对像 Jison 这样的解析器一般来说是个新手,所以我也想知道是否有任何方法可以简化我当前的规则。
代码:
/* description: Parses math files. */
/* lexical grammar */
%lex
%%
[\n;] {return 'NL';}
\s+ {/* skip whitespace */}
"=" {return '=';}
[0-9]+("."[0-9]+)?\b {return 'NUMBER';}
"*" {return '*';}
"/" {return '/';}
"-" {return '-';}
"+" {return '+';}
"^" {return '^';}
"(" {return '(';}
")" {return ')';}
[a-zA-Z]+ {return 'ID';}
"," {return ',';}
"|" {return '|';}
"!" {return '!';}
<<EOF>> {return 'EOF';}
/lex
/* operator associations and precedence */
%left '|'
%left ','
%left '+' '-'
%left '*' '/'
%left '^'
%left UMINUS
%left '!'
%start program
%% /* language grammar */
program
: statement 'NL' program
{$$ = "";}
| statement EOF
{$$ = "";}
;
statement
: e
{$$ = ;}
| ID '=' e
{identifiers[] = ;}
;
e
: block '+' block
{$$ = + ;}
| block '-' block
{$$ = - ;}
| block '*' block
{$$ = * ;}
| block '/' block
{$$ = / ;}
| block '^' block
{$$ = Math.pow(, );}
| '-' block %prec UMINUS
{$$ = -;}
| block '!'
{$$ = util.factorial();}
| ID '(' csv ')'
{$$ = identifiers[].apply(null, );}
| ID '(' ')'
{$$ = identifiers[]();}
| ID
{$$ = identifiers[];}
| adjmul
| block
;
block
: term
| NUMBER
{$$ = Number(yytext);}
;
term
: '(' e ')'
{$$ = ;}
;
adjmul
: block term
{$$ = * ;}
| block ID
{$$ = * identifiers[];}
;
数字的正则表达式不正确。它不应该在末尾有 \b。词法分析过程通常应该纯粹是将输入的字符流标记为词法成分,而不考虑这些标记是否出现在有效序列中。构成有效标记序列的是语法规则的任务。与您的代码一样, whitespace 通常也会在词法分析阶段被丢弃,除非它有意义,在这种情况下您也会对其进行标记。因此,流 '123 foo' 或 '123foo' 都会产生 NUMBER 后跟 ID 的标记序列,whitespace 与否通常在表达式中无效。因此,在您的情况下,删除 \b 可能会解决问题,但是您的语法可能会允许“7a”(没有 space)和“7a”与 space。如果您不想允许 space,我很想引入一个由数字和单词组成的新词汇标记,然后您的语法会适当地处理它。这使得 whitespace 的概念不在你的语法范围内。