3

いくつかの単純な関数を使用して、 Jison 電卓の例を拡張しようとしています。私は解析とバイソン/ジソンにかなり慣れていませんが、これは私がこれまでに持っているものの一部です:

/* lexical grammar */
%lex

%{
  var funcs = {
    pow: function(a, b) { return Math.pow(a, b); },
    test: function(a) { return a*2; }
  }
%}

%%

\s+                   /* skip whitespace */
[0-9]+("."[0-9]+)?\b  return 'NUMBER'
[a-zA-Z]+             return 'NAME'
","                   return ','
"*"                   return '*'
"("                   return '('
")"                   return ')'
<<EOF>>               return 'EOF'
.                     return 'INVALID'

/lex

%start expressions

%% /* language grammar */
expressions
    : e EOF
      { return $1; }
    ;

expression_list
    : expression_list ',' e
    | e
    ;

e
    : e '*' e
        {$$ = $1*$3;}
    | '(' e ')'
        {$$ = $2;}
    | NUMBER
        {$$ = Number(yytext);}
    | NAME '(' expression_list ')'
        {$$ = funcs[$NAME]($expression_list);}
    ;

問題は、関数が 1 つの引数しか渡されないことです。例えば:

test(2) -> 4
pow(2,3) -> null

実際、console.logの引数を指定すると、定義すらされていないpowように見えます。b関数に送信する前に式リスト全体を解析しないのはなぜですか?

4

2 に答える 2

4

次のコードは、あなたが求めたことを実行します。顕著な点:

  1. 現在のルールはexpression_list、呼び出される関数で使用される値の実際のリストを作成します。

  2. によって構築されたリストは、呼び出される関数の引数になるように にexpression_list渡されます (の値を設定する最初の引数として to があります) 。applyundefinedthisundefined

  3. 結果のパーサーをコマンド ラインで実行したときに何が起こっているかを確認できるようconsole.logに、アクションに命令を追加しました。expression

  4. の定義をfuncs最初に移動しました。それがジソンだった場所は、最終ファイルの適切な場所に配置されていませんでした。

最終的なファイルは次のとおりです。

%{var funcs = {
    pow: function(a, b) { return Math.pow(a, b); },
    test: function(a) { return a*2; }
  }
%}

/* lexical grammar */
%lex

%%

\s+                   /* skip whitespace */
[0-9]+("."[0-9]+)?\b  return 'NUMBER'
[a-zA-Z]+             return 'NAME'
","                   return ','
"*"                   return '*'
"("                   return '('
")"                   return ')'
<<EOF>>               return 'EOF'
.                     return 'INVALID'

/lex

%start expressions

%% /* language grammar */
expressions
    : e EOF
      { console.log($1); return $1; }
    ;

expression_list
    : expression_list ',' e
      { $$ = $1.concat([$3]); }
    | e
      { $$ = [$1]; }
    ;

e
    : e '*' e
        {$$ = $1*$3;}
    | '(' e ')'
        {$$ = $2;}
    | NUMBER
        {$$ = Number(yytext);}
    | NAME '(' expression_list ')'
        {$$ = funcs[$NAME].apply(undefined, $expression_list);}
    ;
于 2014-10-30T20:02:34.500 に答える