Skip to content

Commit

Permalink
allow access to value stack - fixes #168
Browse files Browse the repository at this point in the history
  • Loading branch information
zaach committed Aug 3, 2013
1 parent 4c87799 commit da40bfd
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 12 deletions.
35 changes: 35 additions & 0 deletions examples/inherited.y
@@ -0,0 +1,35 @@
%lex
%%
\s+ {}
(global|local|integer|float) { return yytext; }
[a-zA-Z_]\w* { return 'id'; }
. { return yytext; }
/lex
%%
D
: C T L
;

C
: global
| local
;

T
: integer
| float
;

L
: L ',' id {
console.log("L -> L ',' id ("+yytext+")");
console.log($id + ' is of type ' + $0);
console.log($1 + ' is of class ' + $-1);
}
| id {
console.log("L -> id ("+yytext+")");
console.log($id + ' is of type ' + $0);
console.log($1 + ' is of class ' + $-1);
}
;
%%
29 changes: 17 additions & 12 deletions lib/jison.js
Expand Up @@ -191,7 +191,7 @@ function processOperators (ops) {

generator.buildProductions = function buildProductions(bnf, productions, nonterminals, symbols, operators) {
var actions = [
'/* this == yyval */',
'/* this == yyval */',
this.actionInclude || '',
'var $0 = $$.length - 1;',
'switch (yystate) {'
Expand Down Expand Up @@ -289,11 +289,16 @@ generator.buildProductions = function buildProductions(bnf, productions, nonterm
return names[pl] ? '@'+names[pl] : pl;
});
}
action = action.replace(/([^'"])\$\$|^\$\$/g, '$1this.$').replace(/@[0$]/g, "this._$")
.replace(/\$(\d+)/g, function (_, n) {
return "$$[$0" + (n - rhs.length || '') + "]";
action = action
// replace references to $$ with this.$, and @$ with this._$
.replace(/([^'"])\$\$|^\$\$/g, '$1this.$').replace(/@[0$]/g, "this._$")

// replace semantic value references ($n) with stack value (stack[n])
.replace(/\$(-?\d+)/g, function (_, n) {
return "$$[$0" + (parseInt(n, 10) - rhs.length || '') + "]";
})
.replace(/@(\d+)/g, function (_, n) {
// same as above for location references (@n)
.replace(/@(-?\d+)/g, function (_, n) {
return "_$[$0" + (n - rhs.length || '') + "]";
});
actions.push(action);
Expand Down Expand Up @@ -1294,13 +1299,13 @@ _handle_error:
("'"+(this.terminals_[symbol] || symbol)+"'"));
}
this.parseError(errStr, {
text: this.lexer.match,
token: this.terminals_[symbol] || symbol,
line: this.lexer.yylineno,
loc: yyloc,
expected: expected,
recoverable: (error_rule_depth !== false)
});
text: this.lexer.match,
token: this.terminals_[symbol] || symbol,
line: this.lexer.yylineno,
loc: yyloc,
expected: expected,
recoverable: (error_rule_depth !== false)
});
} else if (preErrorSymbol !== EOF) {
error_rule_depth = locateNearestErrorRecoveryRule(state);
}
Expand Down
45 changes: 45 additions & 0 deletions tests/parser/actions.js
Expand Up @@ -150,6 +150,51 @@ exports["test ambiguous named semantic value"] = function() {
assert.equal(parser.parse('xyx'), "xyx", "return first after reduction");
};

exports["test previous semantic value lookup ($0)"] = function() {
var lexData = {
rules: [
["x", "return 'x';"],
["y", "return 'y';"]
]
};
var grammar = {
bnf: {
"S" :[ ["A B", "return $A + $B"] ],
"A" :[ ['A x', "$$ = $A+'x'"], ['x', "$$ = $1"] ],
"B" :[ ["y", "$$ = $0"] ],
}
};

var parser = new Jison.Parser(grammar);
parser.lexer = new RegExpLexer(lexData);

assert.equal(parser.parse('xxy'), "xxxx", "return first after reduction");
};


exports["test negative semantic value lookup ($-1)"] = function() {
var lexData = {
rules: [
["x", "return 'x';"],
["y", "return 'y';"],
["z", "return 'z';"]
]
};
var grammar = {
bnf: {
"S" :[ ["G A B", "return $G + $A + $B"] ],
"G" :[ ['z', "$$ = $1"] ],
"A" :[ ['A x', "$$ = $A+'x'"], ['x', "$$ = $1"] ],
"B" :[ ["y", "$$ = $-1"] ],
}
};

var parser = new Jison.Parser(grammar);
parser.lexer = new RegExpLexer(lexData);

assert.equal(parser.parse('zxy'), "zxz", "return first after reduction");
};

exports["test Build AST"] = function() {
var lexData = {
rules: [
Expand Down

0 comments on commit da40bfd

Please sign in to comment.