TestParserExec tests pass now.

- A few more adjustments to make this test group pass.
- Fixed a few issues in C++ runtime as well.
This commit is contained in:
Mike Lischke 2016-06-01 10:22:48 +02:00
parent 814a1821be
commit 86014ac3a6
25 changed files with 200 additions and 123 deletions

View File

@ -188,7 +188,7 @@ Concat(a,b) ::= "<a><b>"
DeclareLocal(s,v) ::= "<s> = <v>"
AssertIsList(v) ::= "assert isinstance(v, (list, tuple))"
AssertIsList(v) ::= "assert(<v>.size() >= 0);" // Use a method that exists only on a list (vector actually).
AssignLocal(s,v) ::= "<s> = <v>"
@ -250,13 +250,14 @@ LL_EXACT_AMBIG_DETECTION() ::= <<getInterpreter\<atn::ParserATNSimulator>()->set
ParserPropertyMember() ::= <<
@members {
bool Parser::Property() {
bool Property() {
return true;
}
}
>>
ParserPropertyCall(p, call) ::= "<call>"
PositionAdjustingLexer() ::= <<
protected:
class PositionAdjustingLexerATNSimulator : public atn::LexerATNSimulator {
@ -440,7 +441,8 @@ Declare_foo() ::= <<void foo() {
Invoke_foo() ::= "foo();"
Declare_pred() ::= <<void pred(v) {
Declare_pred() ::= <<
void pred(v) {
std::cout \<\< "eval=" \<\< v->toString().lower();
return v;
}
@ -448,6 +450,9 @@ Declare_pred() ::= <<void pred(v) {
Invoke_pred(v) ::= <<pred(<v>)>>
ParserTokenType(t) ::= "Parser::<t>"
ContextRuleFunction(ctx, rule) ::= "<ctx>-><rule>"
isEmpty ::= [
"": true,
default: false

View File

@ -235,6 +235,8 @@ bool Property() {
}
>>
ParserPropertyCall(p, call) ::= "<p>.<call>"
PositionAdjustingLexer() ::= <<
public override IToken NextToken() {
@ -417,6 +419,9 @@ Declare_pred() ::= <<bool pred(bool v) {
Invoke_pred(v) ::= <<this.pred(<v>)>>
ParserTokenType(t) ::= "Parser.<t>"
ContextRuleFunction(ctx, rule) ::= "<ctx>.<rule>"
isEmpty ::= [
"": true,
default: false

View File

@ -238,6 +238,8 @@ boolean Property() {
}
>>
ParserPropertyCall(p, call) ::= "<p>.<call>"
PositionAdjustingLexer() ::= <<
@Override
@ -422,6 +424,9 @@ IgnoredTests ::= [
default: false
]
ParserTokenType(t) ::= "Parser.<t>"
ContextRuleFunction(ctx, rule) ::= "<ctx>.<rule>"
isEmpty ::= [
"": true,
default: false

View File

@ -428,6 +428,8 @@ Declare_pred() ::= <<this.pred = function(v) {
Invoke_pred(v) ::= <<this.pred(<v>)>>
ParserToken(t) ::= "Parser.<t>"
isEmpty ::= [
"": true,
default: false

View File

@ -241,6 +241,8 @@ this.Property = function() {
}
>>
ParserPropertyCall(p, call) ::= "<p>.<call>"
PositionAdjustingLexer() ::= <<
PositionAdjustingLexer.prototype.resetAcceptPosition = function(index, line, column) {
@ -428,6 +430,9 @@ Declare_pred() ::= <<this.pred = function(v) {
Invoke_pred(v) ::= <<this.pred(<v>)>>
ParserTokenType(t) ::= "Parser.<t>"
ContextRuleFunction(ctx, rule) ::= "<ctx>.<rule>"
isEmpty ::= [
"": true,
default: false

View File

@ -243,6 +243,8 @@ this.Property = function() {
}
>>
ParserPropertyCall(p, call) ::= "<p>.<call>"
PositionAdjustingLexer() ::= <<
PositionAdjustingLexer.prototype.resetAcceptPosition = function(index, line, column) {
@ -430,6 +432,9 @@ Declare_pred() ::= <<this.pred = function(v) {
Invoke_pred(v) ::= <<this.pred(<v>)>>
ParserTokenType(t) ::= "Parser.<t>"
ContextRuleFunction(ctx, rule) ::= "<ctx>.<rule>"
isEmpty ::= [
"": true,
default: false

View File

@ -241,6 +241,8 @@ this.Property = function() {
}
>>
ParserPropertyCall(p, call) ::= "<p>.<call>"
PositionAdjustingLexer() ::= <<
PositionAdjustingLexer.prototype.resetAcceptPosition = function(index, line, column) {
@ -432,6 +434,9 @@ Declare_pred() ::= <<this.pred = function(v) {
Invoke_pred(v) ::= <<this.pred(<v>)>>
ParserTokenType(t) ::= "Parser.<t>"
ContextRuleFunction(ctx, rule) ::= "<ctx>.<rule>"
isEmpty ::= [
"": true,
default: false

View File

@ -241,6 +241,8 @@ this.Property = function() {
}
>>
ParserPropertyCall(p, call) ::= "<p>.<call>"
PositionAdjustingLexer() ::= <<
PositionAdjustingLexer.prototype.resetAcceptPosition = function(index, line, column) {
@ -429,6 +431,9 @@ Declare_pred() ::= <<this.pred = function(v) {
Invoke_pred(v) ::= <<this.pred(<v>)>>
ParserTokenType(t) ::= "Parser.<t>"
ContextRuleFunction(ctx, rule) ::= "<ctx>.<rule>"
isEmpty ::= [
"": true,
default: false

View File

@ -245,6 +245,8 @@ def Property(self):
}
>>
ParserPropertyCall(p, call) ::= "<p>.<call>"
PositionAdjustingLexer() ::= <<
def resetAcceptPosition(self, index, line, column):
@ -406,6 +408,9 @@ Declare_pred() ::= <<def pred(self, v):
Invoke_pred(v) ::= <<self.pred(<v>)>>
ParserTokenType(t) ::= "Parser.<t>"
ContextRuleFunction(ctx, rule) ::= "<ctx>.<rule>"
isEmpty ::= [
"": true,
default: false

View File

@ -247,6 +247,8 @@ def Property(self):
}
>>
ParserPropertyCall(p, call) ::= "<p>.<call>"
PositionAdjustingLexer() ::= <<
def resetAcceptPosition(self, index, line, column):
@ -388,6 +390,9 @@ Declare_pred() ::= <<def pred(self, v):
Invoke_pred(v) ::= <<self.pred(<v>)>>
ParserTokenType(t) ::= "Parser.<t>"
ContextRuleFunction(ctx, rule) ::= "<ctx>.<rule>"
isEmpty ::= [
"": true,
default: false

View File

@ -26,7 +26,7 @@ grammar(grammarName) ::= <<
grammar <grammarName>;
ifStatement
@after {
<AssertIsList("$ctx.elseIfStatement()")>
<AssertIsList({<ContextRuleFunction("$ctx", "elseIfStatement()")>})>
}
: 'if' expression
( ( 'then'

View File

@ -27,7 +27,7 @@ Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
<ParserPropertyMember()>
a : {$parser.Property()}? ID {<writeln("\"valid\"")>}
a : {<ParserPropertyCall({$parser}, "Property()")>}? ID {<writeln("\"valid\"")>}
;
ID : 'a'..'z'+ ;
WS : (' '|'\n') -> skip ;

View File

@ -25,7 +25,7 @@ grammar(grammarName) ::= <<
grammar <grammarName>;
s : stmt EOF ;
stmt : ifStmt | ID;
ifStmt : 'if' ID stmt ('else' stmt | { <LANotEquals("1", {<grammarName>Parser.ELSE})> }?);
ifStmt : 'if' ID stmt ('else' stmt | { <LANotEquals("1", {<grammarName><ParserTokenType("ELSE")>})> }?);
ELSE : 'else';
ID : [a-zA-Z]+;
WS : [ \\n\\t]+ -> skip;

View File

@ -13,10 +13,10 @@ public class TestParserExec extends BaseCppTest {
public void testAPlus() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(92);
StringBuilder grammarBuilder = new StringBuilder(97);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : ID+ {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+;\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip;");
@ -36,10 +36,10 @@ public class TestParserExec extends BaseCppTest {
public void testAStar_1() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(92);
StringBuilder grammarBuilder = new StringBuilder(97);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : ID* {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+;\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip;");
@ -59,10 +59,10 @@ public class TestParserExec extends BaseCppTest {
public void testAStar_2() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(92);
StringBuilder grammarBuilder = new StringBuilder(97);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : ID* {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+;\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip;");
@ -82,10 +82,10 @@ public class TestParserExec extends BaseCppTest {
public void testAorAPlus() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(97);
StringBuilder grammarBuilder = new StringBuilder(102);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : (ID|ID)+ {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+;\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip;");
@ -105,10 +105,10 @@ public class TestParserExec extends BaseCppTest {
public void testAorAStar_1() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(97);
StringBuilder grammarBuilder = new StringBuilder(102);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : (ID|ID)* {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+;\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip;");
@ -128,10 +128,10 @@ public class TestParserExec extends BaseCppTest {
public void testAorAStar_2() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(97);
StringBuilder grammarBuilder = new StringBuilder(102);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : (ID|ID)* {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+;\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip;");
@ -151,12 +151,12 @@ public class TestParserExec extends BaseCppTest {
public void testAorB() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(152);
StringBuilder grammarBuilder = new StringBuilder(162);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : ID {\n");
grammarBuilder.append("std::cout << \"alt 1\" << \"\\n\";\n");
grammarBuilder.append("std::cout << \"alt 1\" << std::endl;\n");
grammarBuilder.append("} | INT {\n");
grammarBuilder.append("std::cout << \"alt 2\" << \"\\n\";\n");
grammarBuilder.append("std::cout << \"alt 2\" << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("INT : '0'..'9'+;\n");
@ -177,11 +177,11 @@ public class TestParserExec extends BaseCppTest {
public void testAorBPlus() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(120);
StringBuilder grammarBuilder = new StringBuilder(125);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : (ID|INT{\n");
grammarBuilder.append("})+ {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("INT : '0'..'9'+;\n");
@ -202,11 +202,11 @@ public class TestParserExec extends BaseCppTest {
public void testAorBStar_1() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(120);
StringBuilder grammarBuilder = new StringBuilder(125);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : (ID|INT{\n");
grammarBuilder.append("})* {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("INT : '0'..'9'+;\n");
@ -227,11 +227,11 @@ public class TestParserExec extends BaseCppTest {
public void testAorBStar_2() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(120);
StringBuilder grammarBuilder = new StringBuilder(125);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : (ID|INT{\n");
grammarBuilder.append("})* {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("INT : '0'..'9'+;\n");
@ -252,10 +252,10 @@ public class TestParserExec extends BaseCppTest {
public void testBasic() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(113);
StringBuilder grammarBuilder = new StringBuilder(118);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : ID INT {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("INT : '0'..'9'+;\n");
@ -296,12 +296,12 @@ public class TestParserExec extends BaseCppTest {
public void testIfIfElseGreedyBinding1() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(201);
StringBuilder grammarBuilder = new StringBuilder(206);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("start : statement+ ;\n");
grammarBuilder.append("statement : 'x' | ifStatement;\n");
grammarBuilder.append("ifStatement : 'if' 'y' statement ('else' statement)? {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("WS : (' '|'\\n') -> channel(HIDDEN);");
@ -323,12 +323,12 @@ public class TestParserExec extends BaseCppTest {
public void testIfIfElseGreedyBinding2() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(201);
StringBuilder grammarBuilder = new StringBuilder(206);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("start : statement+ ;\n");
grammarBuilder.append("statement : 'x' | ifStatement;\n");
grammarBuilder.append("ifStatement : 'if' 'y' statement ('else' statement|) {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("WS : (' '|'\\n') -> channel(HIDDEN);");
@ -350,12 +350,12 @@ public class TestParserExec extends BaseCppTest {
public void testIfIfElseNonGreedyBinding1() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(202);
StringBuilder grammarBuilder = new StringBuilder(207);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("start : statement+ ;\n");
grammarBuilder.append("statement : 'x' | ifStatement;\n");
grammarBuilder.append("ifStatement : 'if' 'y' statement ('else' statement)?? {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("WS : (' '|'\\n') -> channel(HIDDEN);");
@ -377,12 +377,12 @@ public class TestParserExec extends BaseCppTest {
public void testIfIfElseNonGreedyBinding2() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(201);
StringBuilder grammarBuilder = new StringBuilder(206);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("start : statement+ ;\n");
grammarBuilder.append("statement : 'x' | ifStatement;\n");
grammarBuilder.append("ifStatement : 'if' 'y' statement (|'else' statement) {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("WS : (' '|'\\n') -> channel(HIDDEN);");
@ -404,10 +404,10 @@ public class TestParserExec extends BaseCppTest {
public void testLL1OptionalBlock_1() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(118);
StringBuilder grammarBuilder = new StringBuilder(123);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : (ID|{}INT)? {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+;\n");
grammarBuilder.append("INT : '0'..'9'+ ;\n");
@ -428,10 +428,10 @@ public class TestParserExec extends BaseCppTest {
public void testLL1OptionalBlock_2() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(118);
StringBuilder grammarBuilder = new StringBuilder(123);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : (ID|{}INT)? {\n");
grammarBuilder.append("std::cout << $text << \"\\n\";\n");
grammarBuilder.append("std::cout << $text << std::endl;\n");
grammarBuilder.append("};\n");
grammarBuilder.append("ID : 'a'..'z'+;\n");
grammarBuilder.append("INT : '0'..'9'+ ;\n");
@ -452,12 +452,12 @@ public class TestParserExec extends BaseCppTest {
public void testLabelAliasingAcrossLabeledAlternatives() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(187);
StringBuilder grammarBuilder = new StringBuilder(197);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("start : a* EOF;\n");
grammarBuilder.append("a\n");
grammarBuilder.append(" : label=subrule {std::cout << $label.text << \"\\n\";} #One\n");
grammarBuilder.append(" | label='y' {std::cout << $label.text << \"\\n\";} #Two\n");
grammarBuilder.append(" : label=subrule {std::cout << $label.text << std::endl;} #One\n");
grammarBuilder.append(" | label='y' {std::cout << $label.text << std::endl;} #Two\n");
grammarBuilder.append(" ;\n");
grammarBuilder.append("subrule : 'x';\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip ;");
@ -502,11 +502,11 @@ public class TestParserExec extends BaseCppTest {
public void testListLabelForClosureContext() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(456);
StringBuilder grammarBuilder = new StringBuilder(465);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("ifStatement\n");
grammarBuilder.append("@after {\n");
grammarBuilder.append("assert isinstance(v, (list, tuple))\n");
grammarBuilder.append("assert($ctx->elseIfStatement().size() >= 0);\n");
grammarBuilder.append("}\n");
grammarBuilder.append(" : 'if' expression\n");
grammarBuilder.append(" ( ( 'then'\n");
@ -666,15 +666,14 @@ public class TestParserExec extends BaseCppTest {
public void testParserProperty() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(174);
StringBuilder grammarBuilder = new StringBuilder(162);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("@members {\n");
grammarBuilder.append("bool Parser::Property() {\n");
grammarBuilder.append("bool Property() {\n");
grammarBuilder.append(" return true;\n");
grammarBuilder.append("}\n");
grammarBuilder.append("\n");
grammarBuilder.append("}\n");
grammarBuilder.append("a : {$parser.Property()}? ID {std::cout << \"valid\" << \"\\n\";}\n");
grammarBuilder.append("a : {Property()}? ID {std::cout << \"valid\" << std::endl;}\n");
grammarBuilder.append(" ;\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip ;");
@ -694,11 +693,11 @@ public class TestParserExec extends BaseCppTest {
public void testPredicatedIfIfElse() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(171);
StringBuilder grammarBuilder = new StringBuilder(174);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("s : stmt EOF ;\n");
grammarBuilder.append("stmt : ifStmt | ID;\n");
grammarBuilder.append("ifStmt : 'if' ID stmt ('else' stmt | { _input->LA(1)!=TParser.ELSE }?);\n");
grammarBuilder.append("ifStmt : 'if' ID stmt ('else' stmt | { _input->LA(1) != TParser::ELSE }?);\n");
grammarBuilder.append("ELSE : 'else';\n");
grammarBuilder.append("ID : [a-zA-Z]+;\n");
grammarBuilder.append("WS : [ \\n\\t]+ -> skip;");
@ -718,13 +717,13 @@ public class TestParserExec extends BaseCppTest {
public void testPredictionIssue334() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(254);
StringBuilder grammarBuilder = new StringBuilder(273);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("file_ @init{\n");
grammarBuilder.append("_errHandler = BailErrorStrategy()\n");
grammarBuilder.append("_errHandler = std::make_shared<BailErrorStrategy>();\n");
grammarBuilder.append("} \n");
grammarBuilder.append("@after {\n");
grammarBuilder.append("std::cout << $ctx.toStringTree(recog=self) << \"\\n\";\n");
grammarBuilder.append("std::cout << $ctx->toStringTree(this) << std::endl;\n");
grammarBuilder.append("}\n");
grammarBuilder.append(" : item (SEMICOLON item)* SEMICOLON? EOF ;\n");
grammarBuilder.append("item : A B?;\n");
@ -748,9 +747,9 @@ public class TestParserExec extends BaseCppTest {
public void testReferenceToATN_1() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(121);
StringBuilder grammarBuilder = new StringBuilder(126);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : (ID|ATN)* ATN? {std::cout << $text << \"\\n\";} ;\n");
grammarBuilder.append("a : (ID|ATN)* ATN? {std::cout << $text << std::endl;} ;\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("ATN : '0'..'9'+;\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip ;");
@ -770,9 +769,9 @@ public class TestParserExec extends BaseCppTest {
public void testReferenceToATN_2() throws Exception {
mkdir(tmpdir);
StringBuilder grammarBuilder = new StringBuilder(121);
StringBuilder grammarBuilder = new StringBuilder(126);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : (ID|ATN)* ATN? {std::cout << $text << \"\\n\";} ;\n");
grammarBuilder.append("a : (ID|ATN)* ATN? {std::cout << $text << std::endl;} ;\n");
grammarBuilder.append("ID : 'a'..'z'+ ;\n");
grammarBuilder.append("ATN : '0'..'9'+;\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip ;");

View File

@ -159,8 +159,7 @@ std::string ParserRuleContext::toInfoString(Parser *recognizer) {
std::vector<std::string> rules = recognizer->getRuleInvocationStack(shared_from_this());
std::reverse(rules.begin(), rules.end());
std::string rulesStr = antlrcpp::arrayToString(rules);
return std::string("ParserRuleContext") + rulesStr + std::string("{") + std::string("start=") +
std::to_string(start->getTokenIndex()) + std::string(", stop=") +
return "ParserRuleContext" + rulesStr + "{start=" + std::to_string(start->getTokenIndex()) + ", stop=" +
std::to_string(stop->getTokenIndex()) + '}';
}

View File

@ -78,8 +78,8 @@ size_t ATNConfig::hashCode() const {
size_t hashCode = misc::MurmurHash::initialize(7);
hashCode = misc::MurmurHash::update(hashCode, (size_t)state->stateNumber);
hashCode = misc::MurmurHash::update(hashCode, (size_t)alt);
hashCode = misc::MurmurHash::update(hashCode, context ? context->hashCode() : 0);
hashCode = misc::MurmurHash::update(hashCode, semanticContext->hashCode());
hashCode = misc::MurmurHash::update(hashCode, context);
hashCode = misc::MurmurHash::update(hashCode, semanticContext);
hashCode = misc::MurmurHash::finish(hashCode, 4);
return hashCode;
}

View File

@ -47,10 +47,21 @@ namespace atn {
/// </summary>
class ANTLR4CPP_PUBLIC ATNConfig {
public:
struct ATNConfigHasher;
struct ATNConfigComparer;
struct Hasher
{
size_t operator()(const ATNConfig &k) const {
return k.hashCode();
}
};
using Set = std::unordered_set<Ref<ATNConfig>, ATNConfigHasher, ATNConfigComparer>;
struct Comparer {
bool operator()(const ATNConfig &lhs, const ATNConfig &rhs) const {
return lhs == rhs;
}
};
using Set = std::unordered_set<Ref<ATNConfig>, Hasher, Comparer>;
/// The ATN state associated with this configuration.
ATNState * state;
@ -108,20 +119,6 @@ namespace atn {
virtual size_t hashCode() const;
struct ATNConfigHasher
{
size_t operator()(const ATNConfig &k) const {
return k.hashCode();
}
};
struct ATNConfigComparer {
bool operator()(const ATNConfig &lhs, const ATNConfig &rhs) const
{
return lhs == rhs;
}
};
/**
* This method gets the value of the {@link #reachesIntoOuterContext} field
* as it existed prior to the introduction of the

View File

@ -44,7 +44,7 @@ size_t SimpleATNConfigHasher::operator()(const Ref<ATNConfig> &k) const {
size_t hashCode = 7;
hashCode = 31 * hashCode + (size_t)k->state->stateNumber;
hashCode = 31 * hashCode + (size_t)k->alt;
hashCode = 31 * hashCode + k->semanticContext->hashCode();
hashCode = 31 * hashCode + (k->semanticContext == nullptr ? 0 : k->semanticContext->hashCode());
return hashCode;
}

View File

@ -79,8 +79,8 @@ size_t LexerATNConfig::hashCode() const {
size_t hashCode = misc::MurmurHash::initialize(7);
hashCode = misc::MurmurHash::update(hashCode, (size_t)state->stateNumber);
hashCode = misc::MurmurHash::update(hashCode, (size_t)alt);
hashCode = misc::MurmurHash::update(hashCode, context->hashCode());
hashCode = misc::MurmurHash::update(hashCode, semanticContext->hashCode());
hashCode = misc::MurmurHash::update(hashCode, context);
hashCode = misc::MurmurHash::update(hashCode, semanticContext);
hashCode = misc::MurmurHash::update(hashCode, _passedThroughNonGreedyDecision ? 1 : 0);
hashCode = misc::MurmurHash::update(hashCode, _lexerActionExecutor ? _lexerActionExecutor->hashCode() : 0);
hashCode = misc::MurmurHash::finish(hashCode, 6);

View File

@ -1058,7 +1058,7 @@ Ref<ATNConfig> ParserATNSimulator::precedenceTransition(Ref<ATNConfig> config, P
c = std::make_shared<ATNConfig>(config, pt->target); // no pred context
}
} else {
Ref<SemanticContext::AND> newSemCtx = std::make_shared<SemanticContext::AND>(config->semanticContext, predicate);
Ref<SemanticContext> newSemCtx = SemanticContext::And(config->semanticContext, predicate);
c = std::make_shared<ATNConfig>(config, pt->target, newSemCtx);
}
} else {
@ -1096,7 +1096,7 @@ Ref<ATNConfig> ParserATNSimulator::predTransition(Ref<ATNConfig> config, Predica
c = std::make_shared<ATNConfig>(config, pt->target); // no pred context
}
} else {
Ref<SemanticContext::AND> newSemCtx = std::make_shared<SemanticContext::AND>(config->semanticContext, predicate);
Ref<SemanticContext> newSemCtx = SemanticContext::And(config->semanticContext, predicate);
c = std::make_shared<ATNConfig>(config, pt->target, newSemCtx);
}
} else {

View File

@ -50,7 +50,7 @@ struct AltAndContextConfigHasher
size_t operator () (const ATNConfig &o) const {
size_t hashCode = misc::MurmurHash::initialize(7);
hashCode = misc::MurmurHash::update(hashCode, (size_t)o.state->stateNumber);
hashCode = misc::MurmurHash::update(hashCode, o.context->hashCode());
hashCode = misc::MurmurHash::update(hashCode, o.context);
return misc::MurmurHash::finish(hashCode, 2);
}
};

View File

@ -133,35 +133,37 @@ std::string SemanticContext::PrecedencePredicate::toString() const {
//------------------ AND -----------------------------------------------------------------------------------------------
SemanticContext::AND::AND(Ref<SemanticContext> a, Ref<SemanticContext> b) {
Set operands;
if (is<AND>(a)) {
const std::vector<Ref<SemanticContext>> op = ((AND*)a.get())->opnds;
for (auto var : op) {
opnds.push_back(var);
for (auto operand : std::dynamic_pointer_cast<AND>(a)->opnds) {
operands.insert(operand);
}
} else {
opnds.push_back(a);
operands.insert(a);
}
if (is<AND>(b)) {
const std::vector<Ref<SemanticContext>> op = ((AND*)b.get())->opnds;
for (auto var : op) {
opnds.push_back(var);
for (auto operand : std::dynamic_pointer_cast<AND>(b)->opnds) {
operands.insert(operand);
}
} else {
opnds.push_back(b);
operands.insert(b);
}
std::vector<Ref<PrecedencePredicate>> precedencePredicates = filterPrecedencePredicates(opnds);
std::vector<Ref<PrecedencePredicate>> precedencePredicates = filterPrecedencePredicates(operands);
if (!precedencePredicates.empty()) {
// interested in the transition with the lowest precedence
auto predicate = [](Ref<PrecedencePredicate> a, Ref<PrecedencePredicate> b) {
return a->precedence < b->precedence;
};
auto reduced = std::min_element(precedencePredicates.begin(), precedencePredicates.end(), predicate);
opnds.push_back(*reduced);
operands.insert(*reduced);
}
std::copy(operands.begin(), operands.end(), std::back_inserter(opnds));
}
std::vector<Ref<SemanticContext>> SemanticContext::AND::getOperands() const {
@ -236,33 +238,35 @@ std::string SemanticContext::AND::toString() const {
//------------------ OR ------------------------------------------------------------------------------------------------
SemanticContext::OR::OR(Ref<SemanticContext> a, Ref<SemanticContext> b) {
Set operands;
if (is<OR>(a)) {
const std::vector<Ref<SemanticContext>> op = ((OR*)a.get())->opnds;
for (auto var : op) {
opnds.push_back(var);
for (auto operand : std::dynamic_pointer_cast<OR>(a)->opnds) {
operands.insert(operand);
}
} else {
opnds.push_back(a);
operands.insert(a);
}
if (is<OR>(b)) {
const std::vector<Ref<SemanticContext>> op = ((OR*)b.get())->opnds;
for (auto var : op) {
opnds.push_back(var);
for (auto operand : std::dynamic_pointer_cast<OR>(b)->opnds) {
operands.insert(operand);
}
} else {
opnds.push_back(b);
operands.insert(b);
}
std::vector<Ref<PrecedencePredicate>> precedencePredicates = filterPrecedencePredicates(opnds);
std::vector<Ref<PrecedencePredicate>> precedencePredicates = filterPrecedencePredicates(operands);
if (!precedencePredicates.empty()) {
// interested in the transition with the highest precedence
auto predicate = [](Ref<PrecedencePredicate> a, Ref<PrecedencePredicate> b) {
return a->precedence > b->precedence;
return a->precedence < b->precedence;
};
auto reduced = std::min_element(precedencePredicates.begin(), precedencePredicates.end(), predicate);
opnds.push_back(*reduced);
auto reduced = std::max_element(precedencePredicates.begin(), precedencePredicates.end(), predicate);
operands.insert(*reduced);
}
std::copy(operands.begin(), operands.end(), std::back_inserter(opnds));
}
std::vector<Ref<SemanticContext>> SemanticContext::OR::getOperands() const {
@ -378,3 +382,14 @@ Ref<SemanticContext> SemanticContext::Or(Ref<SemanticContext> a, Ref<SemanticCon
return result;
}
std::vector<Ref<SemanticContext::PrecedencePredicate>> SemanticContext::filterPrecedencePredicates(const Set &collection) {
std::vector<Ref<SemanticContext::PrecedencePredicate>> result;
for (auto context : collection) {
if (antlrcpp::is<PrecedencePredicate>(context)) {
result.push_back(std::dynamic_pointer_cast<PrecedencePredicate>(context));
}
}
return result;
}

View File

@ -48,6 +48,22 @@ namespace atn {
/// SemanticContext within the scope of this outer class.
class ANTLR4CPP_PUBLIC SemanticContext : public std::enable_shared_from_this<SemanticContext> {
public:
struct Hasher
{
size_t operator()(Ref<SemanticContext> k) const {
return k->hashCode();
}
};
struct Comparer {
bool operator()(Ref<SemanticContext> lhs, Ref<SemanticContext> rhs) const {
return *lhs == *rhs;
}
};
using Set = std::unordered_set<Ref<SemanticContext>, Hasher, Comparer>;
/**
* The default {@link SemanticContext}, which is semantically equivalent to
* a predicate of the form {@code {true}?}.
@ -107,18 +123,7 @@ namespace atn {
class OR;
private:
template<typename T1> // where T1 : SemanticContext>
static std::vector<Ref<PrecedencePredicate>> filterPrecedencePredicates(const std::vector<T1> &collection) {
std::vector<Ref<PrecedencePredicate>> result;
for (auto context : collection) {
if (antlrcpp::is<PrecedencePredicate>(context)) {
result.push_back(std::dynamic_pointer_cast<PrecedencePredicate>(context));
}
}
return result;
}
static std::vector<Ref<PrecedencePredicate>> filterPrecedencePredicates(const Set &collection);
};
class ANTLR4CPP_PUBLIC SemanticContext::Predicate : public SemanticContext {
@ -236,7 +241,7 @@ namespace std {
template <> struct hash<SemanticContext>
{
size_t operator () ( SemanticContext &x) const
size_t operator () (SemanticContext &x) const
{
return x.hashCode();
}

View File

@ -58,6 +58,18 @@ namespace misc {
/// Returns the updated intermediate hash value.
static size_t update(size_t hash, size_t value);
/**
* Update the intermediate hash value for the next input {@code value}.
*
* @param hash the intermediate hash value
* @param value the value to add to the current hash
* @return the updated intermediate hash value
*/
template <class T>
static size_t update(size_t hash, Ref<T> value) {
return update(hash, value != nullptr ? value->hashCode() : 0);
}
/// <summary>
/// Apply the final computation steps to the intermediate value {@code hash}
/// to form the final result of the MurmurHash 3 hash function.

View File

@ -929,6 +929,9 @@ ThisRulePropertyRef_text(r) ::= "_input->getText(_localctx->start, _input->LT(-
ThisRulePropertyRef_ctxHeader(r) ::= "<! Required but unused. !>"
ThisRulePropertyRef_ctx(r) ::= "_localctx"
ThisRulePropertyRef_parserHeader(r) ::= "<! Required but unused. !>"
ThisRulePropertyRef_parser(r) ::= "this"
NonLocalAttrRef(s) ::= "NonLocalAttrRef(s) ((<s.ruleName; format=\"cap\">Context)getInvokingContext(<s.ruleIndex>)).<s.name>"
SetNonLocalAttr(s, rhsChunks) ::=
"SetNonLocalAttr(s, rhsChunks) ((<s.ruleName; format=\"cap\">Context)getInvokingContext(<s.ruleIndex>)).<s.name> = <rhsChunks>;"
@ -1014,7 +1017,7 @@ ImplicitTokenLabel(tokenName) ::= <<
>>
ImplicitRuleLabel(ruleName) ::= "<ruleName>Context"
ImplicitSetLabel(id) ::= "ImplicitSetLabel(id) _tset<id>"
ImplicitSetLabel(id) ::= "_tset<id>"
ListLabelName(label) ::= "<label>"
CaptureNextToken(d) ::= "CaptureNextToken(d) <d.varName> = _input->LT(1);"