2014-10-30 87 views
2

我試圖用一些簡單的函數來擴展Jison calculator example。我是相當新的解析和野牛/ jison,但這一點是我到目前爲止有:將函數添加到野牛/ 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);} 
    ; 

的問題是功能只得到傳遞給他們一個說法。例如:

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

事實上,如果你console.logpow的論點,似乎b甚至沒有定義。爲什麼不在發送給函數之前解析整個表達式列表?

回答

1

您需要在第一次生產expression_list時採取措施。默認操作只是將$1複製到$$,這意味着附加值將被丟棄。

+0

謝謝你解釋它是如何工作! – whereswalden 2014-10-30 20:19:12

2

以下代碼不會滿足您的要求。要點:

  1. expression_list規則現在建立值的實際列表與被調用的函數中使用。

  2. 通過expression_list建立的列表被傳遞到apply,使他們成爲被調用的函數的參數(undefined是那裏的第一個參數的this值設置爲undefined)。

  3. 我已將console.log指令添加到expression的操作中,以便我在命令行運行生成的解析器時看到發生了什麼。

  4. 我已經將funcs的定義移至最開始。 jison只是沒有把它放在最終文件的正確位置。

這裏的最後文件:

%{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);} 
    ; 
+0

有趣。當我嘗試在那裏移動'funcs'時,[在線解析器生成器](http://zaach.github.io/jison/try/)給了我'funcs沒有定義.'如果我使用'var funcs '而不只是'funcs',這意味着我正在污染全球範圍。任何想法是什麼? – whereswalden 2014-10-30 20:20:25

+0

對於那個特定的問題,我不得不重新閱讀文檔。自從我每天編寫jison代碼以來,這已經過去了幾個月。我的工作假設是,你擁有它的地方,代碼對於詞法分析器來說是本地的。如果在線工具的工作方式不同,則可能它沒有更新到最新版本。 (它似乎是0.4.13,而'npm install'安裝0.4.15。) – Louis 2014-10-30 20:28:30

+1

[看起來聲明在動態生成解析器時不起作用](https://github.com/zaach/jison/issues/ 188)。這解釋了爲什麼它在npm中起作用。 – whereswalden 2014-10-30 20:38:24