0

我最近一直在尝试使用 Jison,我想我会尝试创建一种能够(至少部分)解析一些数学表达式的语法。

但是,现在我对如何创建一个规则感到困惑,该规则将允许乘以先前定义的变量的形式7a(例如) 。a我试图adjmul在我的代码中执行此操作,但解析器不起作用,除非在7and之间存在空格a。简而言之,如果它们在程序中相邻,我将如何创建一个允许数字和变量之间相乘的规则/规则?

由于我对 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
        {$$ = $1;}
    | ID '=' e
        {identifiers[$1] = $3;}
    ;

e
    : block '+' block
        {$$ = $1 + $3;}
    | block '-' block
        {$$ = $1 - $3;}
    | block '*' block
        {$$ = $1 * $3;}
    | block '/' block
        {$$ = $1 / $3;}
    | block '^' block
        {$$ = Math.pow($1, $3);}
    | '-' block %prec UMINUS
        {$$ = -$2;}
    | block '!'
        {$$ = util.factorial($1);}
    | ID '(' csv ')'
        {$$ = identifiers[$1].apply(null, $3);}
    | ID '(' ')'
        {$$ = identifiers[$1]();}
    | ID
        {$$ = identifiers[$1];}
    | adjmul
    | block
    ;

block
    : term
    | NUMBER
        {$$ = Number(yytext);}
    ;

term
    : '(' e ')'
        {$$ = $2;}
    ;

adjmul
    : block term
        {$$ = $1 * $2;}
    | block ID
        {$$ = $1 * identifiers[$2];}
    ;
4

1 回答 1

0

数字的正则表达式不正确。最后不应该有 \b 。词法分析过程通常应该纯粹是关于将输入的字符流标记为词法组件,而不考虑这些标记是否以有效序列出现。包含有效标记序列的是语法规则的任务。与您的代码一样,除非它有意义,否则通常在词法分析阶段也会丢弃空格,在这种情况下,您也会对其进行标记。因此,流 '123 foo' 或 '123foo' 都会产生 NUMBER 后跟 ID 的标记序列,无论是否有空格,通常在表达式中都是无效的。因此,在您的情况下,删除 \b 可能会解决问题,但是您的语法可能会允许 '7a' (没有空格)和 '7 a' 有空格。如果您不想留出空间,我很想引入一个由数字和单词组成的新词汇标记,然后您的语法会适当地处理它们。这将空格的概念保留在语法之外。

于 2015-07-28T10:25:47.367 回答