diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs index e16014115e1..1d4bcb41c23 100644 --- a/.settings/org.eclipse.core.resources.prefs +++ b/.settings/org.eclipse.core.resources.prefs @@ -5,7 +5,6 @@ encoding//src/org/rascalmpl/library/experiments/vis2/lib/nv.d3.css=UTF-8 encoding//src/org/rascalmpl/library/experiments/vis2/lib/nv.d3.js=UTF-8 encoding//src/org/rascalmpl/library/experiments/vis2/lib/reset.css=UTF-8 encoding//src/org/rascalmpl/library/lang/rascal/tests/functionality/DataType.rsc=UTF-8 -encoding//target/generated-resources=UTF-8 encoding//test/org/rascalmpl/test/data=UTF-8 encoding/=UTF-8 encoding/META-INF=UTF-8 diff --git a/.vscode/launch.json b/.vscode/launch.json index fa9529bef36..ea97d164bac 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,41 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "type": "java", + "name": "$GENERATED_PARSER$244372483", + "request": "launch", + "mainClass": "org.rascalmpl.test.parser.$GENERATED_PARSER$244372483", + "projectName": "rascal" + }, + { + "type": "java", + "name": "$GENERATED_PARSER$279786030", + "request": "launch", + "mainClass": "org.rascalmpl.test.parser.$GENERATED_PARSER$279786030", + "projectName": "rascal" + }, + { + "type": "java", + "name": "TopLevelStarListEmpty", + "request": "launch", + "mainClass": "org.rascalmpl.test.parser.TopLevelStarListEmpty", + "projectName": "rascal" + }, + { + "type": "java", + "name": "TopLevelStarList", + "request": "launch", + "mainClass": "org.rascalmpl.test.parser.TopLevelStarList", + "projectName": "rascal" + }, + { + "type": "java", + "name": "NonTerminalStarListEmpty", + "request": "launch", + "mainClass": "org.rascalmpl.test.parser.NonTerminalStarListEmpty", + "projectName": "rascal" + }, { "type": "java", "name": "RascalCheck", diff --git a/src/org/rascalmpl/exceptions/JavaCompilation.java b/src/org/rascalmpl/exceptions/JavaCompilation.java index 4941ca919f1..ca501b70d3b 100644 --- a/src/org/rascalmpl/exceptions/JavaCompilation.java +++ b/src/org/rascalmpl/exceptions/JavaCompilation.java @@ -18,7 +18,7 @@ public class JavaCompilation extends RuntimeException { private final long column; public JavaCompilation(String message, long line, long column, String source, Exception cause) { - super("Java compilation failed due to " + message, cause); + super("Java compilation failed due to " + message + " at " + line + ", " + column, cause); this.source = source; this.line = line; this.column = column; diff --git a/src/org/rascalmpl/library/lang/rascal/grammar/ParserGenerator.rsc b/src/org/rascalmpl/library/lang/rascal/grammar/ParserGenerator.rsc index 08e73272705..3b672988415 100644 --- a/src/org/rascalmpl/library/lang/rascal/grammar/ParserGenerator.rsc +++ b/src/org/rascalmpl/library/lang/rascal/grammar/ParserGenerator.rsc @@ -12,39 +12,64 @@ module lang::rascal::grammar::ParserGenerator import Grammar; -import lang::rascal::grammar::definition::Parameters; -import lang::rascal::grammar::definition::Regular; -import lang::rascal::grammar::definition::Productions; +import IO; +import List; +import Node; +import ParseTree; +import Set; +import String; +import lang::rascal::\syntax::Rascal; +import lang::rascal::grammar::ConcreteSyntax; +import lang::rascal::grammar::Lookahead; +import lang::rascal::grammar::definition::Keywords; +import lang::rascal::grammar::definition::Literals; import lang::rascal::grammar::definition::Modules; +import lang::rascal::grammar::definition::Parameters; import lang::rascal::grammar::definition::Priorities; -import lang::rascal::grammar::definition::Literals; +import lang::rascal::grammar::definition::Productions; +import lang::rascal::grammar::definition::Regular; import lang::rascal::grammar::definition::Symbols; -import lang::rascal::grammar::definition::Keywords; -import lang::rascal::grammar::Lookahead; - import util::Monitor; -import lang::rascal::\syntax::Rascal; -import lang::rascal::grammar::ConcreteSyntax; -import ParseTree; -import String; -import List; -import Node; -import Set; // TODO: replace this complex data structure with several simple ones alias Items = map[Symbol,map[Item item, tuple[str new, int itemId] new]]; data Symbol(int id = 0, str prefix = ""); -public str getParserMethodName(Sym sym) = getParserMethodName(sym2symbol(sym)); -str getParserMethodName(label(_,Symbol s)) = getParserMethodName(s); -str getParserMethodName(conditional(Symbol s, _)) = getParserMethodName(s); -default str getParserMethodName(Symbol s) = value2id(s); +str getParserMethodName(Sym sym, bool withLayout=false) + = getParserMethodName(sym2symbol(sym, withLayout=withLayout)); + +str getParserMethodName(\start(sort(str name)), bool withLayout=false) + = "$start_$s_"; + +str getParserMethodName(layouts(str name), bool withLayout=false) + = "$l_"; + +str getParserMethodName(sort(str name), bool withLayout=false) + = "$s_"; + +str getParserMethodName(lex(str name), bool withLayout=false) + = "$l_"; + +str getParserMethodName(keywords(str name), bool withLayout=false) + = "$k_"; + +str getParserMethodName(label(_,Symbol s), bool withLayout=false) + = getParserMethodName(s, withLayout=withLayout); + +str getParserMethodName(conditional(Symbol s, _), bool withLayout=false) + = getParserMethodName(s, withLayout=withLayout); + +str getParserMethodName(Symbol s, bool withLayout=false) + = "regular_" when s is iter || s is \iter-seps || s is \iter-star || s is \iter-star-seps || s is opt || s is seq || s is empty; + +default str getParserMethodName(Symbol s, bool withLayout=false) + = ""; public str newGenerate(str package, str name, Grammar gr) { return job("Generating parser; <}>"[..-1], str (void (str m, int w) worked) { int uniqueItem = 1; // -1 and -2 are reserved by the SGTDBF implementation - int newItem() { uniqueItem += 1; return uniqueItem; }; + int newItem() { uniqueItem += 2; return uniqueItem; }; // we use only the odd numbers to reserve the even numbers for top-level regular prods worked("expanding parameterized symbols", 1); gr = expandParameterizedSymbols(gr); @@ -90,6 +115,8 @@ public str newGenerate(str package, str name, Grammar gr) { ' 'import java.io.IOException; 'import java.io.StringReader; + 'import java.io.PrintWriter; + 'import java.util.function.Supplier; ' 'import io.usethesource.vallang.type.TypeFactory; 'import io.usethesource.vallang.IConstructor; @@ -98,6 +125,7 @@ public str newGenerate(str package, str name, Grammar gr) { 'import io.usethesource.vallang.IValueFactory; 'import io.usethesource.vallang.exceptions.FactTypeUseException; 'import io.usethesource.vallang.io.StandardTextReader; + 'import io.usethesource.vallang.io.StandardTextWriter; 'import org.rascalmpl.parser.gtd.stack.*; 'import org.rascalmpl.parser.gtd.stack.filter.*; 'import org.rascalmpl.parser.gtd.stack.filter.follow.*; @@ -108,8 +136,11 @@ public str newGenerate(str package, str name, Grammar gr) { 'import org.rascalmpl.parser.gtd.util.IntegerList; 'import org.rascalmpl.parser.gtd.util.IntegerMap; 'import org.rascalmpl.values.ValueFactoryFactory; + 'import org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener; + 'import org.rascalmpl.parser.uptr.UPTRNodeFactory; 'import org.rascalmpl.values.RascalValueFactory; 'import org.rascalmpl.values.parsetrees.ITree; + 'import org.rascalmpl.values.parsetrees.TreeAdapter; ' '@SuppressWarnings(\"all\") 'public class extends org.rascalmpl.parser.gtd.SGTDBF\ { @@ -212,13 +243,15 @@ public str newGenerate(str package, str name, Grammar gr) { } }> ' - ' protected static class { + ' protected static class { ' public final static AbstractStackNode\[] EXPECTS; + ' ' static{ ' ExpectBuilder\ builder = new ExpectBuilder\(_dontNest, _resultStoreIdMappings); ' init(builder); - ' EXPECTS = builder.buildExpectArray(); + ' EXPECTS = builder.buildExpectArray(); ' } + ' ' ' protected static final void _init_(ExpectBuilder\ builder) { ' AbstractStackNode\[] tmp = (AbstractStackNode\[]) new AbstractStackNode[]; @@ -226,11 +259,13 @@ public str newGenerate(str package, str name, Grammar gr) { ' tmp[] = ;<}> ' builder.addAlternative(., tmp); ' }<}> + ' ' public static void init(ExpectBuilder\ builder){ ' ' _init_(builder); ' <}> ' } + ' ' }<}> ' ' private int nextFreeStackNodeId = ; @@ -239,8 +274,27 @@ public str newGenerate(str package, str name, Grammar gr) { ' } ' ' // Parse methods - ' - ' <}> + ' + ' <}> + ' + ' // Debugging utilities + ' private ITree test(Supplier\ method, String example) throws Throwable { + ' return parse(method.get()[0], null, example.toCharArray(), new DefaultNodeFlattener\(), new UPTRNodeFactory(true)); + ' } + ' + ' public static void main(String[] args) throws Throwable { + ' var p = new (); + ' + ' String input = \"???\"; + ' Supplier\ nont = p::<}>; + ' + ' var output = p.test(nont, input); + ' + ' System.err.println(\"parse tree:\"); + ' new StandardTextWriter(true).write(output, new PrintWriter(System.err)); + ' System.err.println(\"\\nyield:\"); + ' System.err.println(TreeAdapter.yield(output)); + ' } '}"; }, totalWork=9); } @@ -363,15 +417,36 @@ bool isNonterminal(Symbol s) { case Symbol::\parameterized-lex(_,_) : return true; case Symbol::\start(_) : return true; case Symbol::\layouts(_) : return true; + + // regulars too from now on: + case Symbol::\iter(_) : return true; + case Symbol::\iter-star(_) : return true; + case Symbol::\iter-seps(_,_) : return true; + case Symbol::\iter-star-seps(_,_) : return true; + case Symbol::seq(_) : return true; + case Symbol::opt(_) : return true; + case Symbol::alt(_) : return true; + case Symbol::empty() : return true; + default: return false; } } -public str generateParseMethod(Items _, Production p) { - return "public AbstractStackNode\[] () { - ' return .EXPECTS; +public default str generateParseMethod(Grammar g, Items _, Production p, int _) + = "public AbstractStackNode\[] () { + ' return .EXPECTS; '}"; -} + + +public str generateParseMethod(Grammar g, Items _, choice(Symbol def, {regular(def)}), int id) +// TODO: here we have to work if we also want regular lexical non-terminals at the top + = "public AbstractStackNode\[] () { + ' return new AbstractStackNode[] { + ' + ' }; + '}"; + + str generateClassConditional(set[Symbol] classes) { if (eoi() in classes) { @@ -505,23 +580,23 @@ public tuple[str new, int itemId] sym2newitem(Grammar grammar, Symbol sym, int d switch (sym) { case Symbol::\sort(_) : - return <"new NonTerminalStackNode\(, , \"\", )", itemId>; + return <"new NonTerminalStackNode\(, , \"\", )", itemId>; case Symbol::\empty() : return <"new EmptyStackNode\(, , , )", itemId>; case Symbol::\lex(_) : - return <"new NonTerminalStackNode\(, , \"\", )", itemId>; + return <"new NonTerminalStackNode\(, , \"\", )", itemId>; case Symbol::\keywords(_) : - return <"new NonTerminalStackNode\(, , \"\", )", itemId>; + return <"new NonTerminalStackNode\(, , \"\", )", itemId>; case Symbol::\layouts(_) : - return <"new NonTerminalStackNode\(, , \"\", )", itemId>; + return <"new NonTerminalStackNode\(, , \"\", )", itemId>; case Symbol::\parameterized-sort(_,_): - return <"new NonTerminalStackNode\(, , \"\", )", itemId>; + return <"new NonTerminalStackNode\(, , \"\", )", itemId>; case Symbol::\parameterized-lex(_,_): - return <"new NonTerminalStackNode\(, , \"\", )", itemId>; + return <"new NonTerminalStackNode\(, , \"\", )", itemId>; case Symbol::\parameter(_, _) : throw "All parameters should have been instantiated by now: "; - case Symbol::\start(_) : - return <"new NonTerminalStackNode\(, , \"\", )", itemId>; + case Symbol::\start(_) : + return <"new NonTerminalStackNode\(, , \", )", itemId>; case Symbol::\lit(l) : if (/p:prod(lit(l,id=_),list[Symbol] chars,_) := grammar.rules[getType(sym)]) return <"new LiteralStackNode\(, , , new int[] {}, )",itemId>; @@ -605,9 +680,15 @@ default str v2i(value v) { switch (v) { case \start(Symbol s) : return "start__"; case item(p:prod(Symbol u,_,_), int i) : return "._"; - case label(str x,Symbol u) : return escId(x) + "_" + v2i(u); - case layouts(str x) : return "layouts_"; + case label(str _x, Symbol u) : return escId(x) + "_" + v2i(u); + case layouts(str _) : return "$anylayout$"; case conditional(Symbol s,_) : return v2i(s); + case \iter-seps(Symbol s, [_]) : return "_iter_seps_"; + case \iter-star-seps(Symbol s, [Symbol sep]) : return "_iter_star_seps__"; + case \iter-seps(Symbol s, [_,Symbol sep,_]) : return "_iter_seps__"; + case \iter-star-seps(Symbol s, [_, Symbol sep, _]) : return "_iter_star_seps___"; + case \seq([Symbol first, layouts(_), *Symbol next]) : return "seq_"; + case \seq(list[Symbol] args) : return "seq_"; case sort(str s) : return ""; case \lex(str s) : return ""; case keywords(str s) : return ""; diff --git a/src/org/rascalmpl/library/lang/rascal/grammar/definition/Layout.rsc b/src/org/rascalmpl/library/lang/rascal/grammar/definition/Layout.rsc index 264db1e4ac8..e3f3814f8fe 100644 --- a/src/org/rascalmpl/library/lang/rascal/grammar/definition/Layout.rsc +++ b/src/org/rascalmpl/library/lang/rascal/grammar/definition/Layout.rsc @@ -12,6 +12,8 @@ import lang::rascal::\syntax::Rascal; import Grammar; import ParseTree; +public Symbol defLayout = layouts("$default$"); + @synopsis{intermixes the actively visible layout definition in each module into the relevant syntax definitions} GrammarDefinition \layouts(GrammarDefinition def) { deps = dependencies(def); @@ -30,12 +32,6 @@ set[Symbol] allLayouts(set[str] defs, GrammarDefinition def) = {sort(l) | m <- defs, def.modules[m]?, /prod(layouts(str l),_,_) := def.modules[m]} + {sort(l) | m <- defs, def.modules[m]?, /prod(label(_,layouts(str l)),_,_) := def.modules[m]} ; - -// TODO, REMOVE THIS: The following two functions were defined local to activeLayout -// but this gives an not yet explained validation error for the -// function ids in the corresponding overloaded function -//bool isManual(set[Attr] as) = (Attr::\tag("manual"()) in as); -//bool isDefault(Symbol s) = (s == layouts("$default$")); @synopsis{computes which layout definitions are visible in a certain given module. if a module contains a layout definition, this overrides any imported layout definition @@ -45,7 +41,7 @@ set[Symbol] allLayouts(set[str] defs, GrammarDefinition def) will just produce an arbitrary one if there are multiple definitions} Symbol activeLayout(str name, set[str] deps, GrammarDefinition def) { bool isManual(set[Attr] as) = (Attr::\tag("manual"()) in as); - bool isDefault(Symbol s) = (s == layouts("$default$")); + bool isDefault(Symbol s) = (s == defLayout); if (/prod(l:layouts(_),_,as) := def.modules[name], !isDefault(l), !isManual(as)) return l; @@ -56,7 +52,7 @@ Symbol activeLayout(str name, set[str] deps, GrammarDefinition def) { else if (i <- deps, def.modules[i]?, /prod(label(_,l:layouts(_)),_,as) := def.modules[i], !isDefault(l), !isManual(as)) return l; else - return layouts("$default$"); + return defLayout; } @synopsis{intersperses layout symbols in all non-lexical productions} diff --git a/src/org/rascalmpl/library/lang/rascal/grammar/definition/Symbols.rsc b/src/org/rascalmpl/library/lang/rascal/grammar/definition/Symbols.rsc index 75ed6d84876..1147c10cdef 100644 --- a/src/org/rascalmpl/library/lang/rascal/grammar/definition/Symbols.rsc +++ b/src/org/rascalmpl/library/lang/rascal/grammar/definition/Symbols.rsc @@ -10,11 +10,11 @@ module lang::rascal::grammar::definition::Symbols import lang::rascal::grammar::definition::Literals; import lang::rascal::grammar::definition::Characters; +import lang::rascal::grammar::definition::Layout; import lang::rascal::\syntax::Rascal; import ParseTree; import String; - default Symbol striprec(Symbol s_ori) = visit(s_ori) { case label(str _, Symbol s) => strip(s) case conditional(Symbol s, set[Condition] _) => strip(s) @@ -35,9 +35,9 @@ public bool match(Symbol checked, Symbol referenced) { public Symbol delabel(Symbol s) = visit(s) { case label(_,t) => t }; -public Symbol sym2symbol(Sym sym) { +public Symbol sym2symbol(Sym sym, bool withLayout=false) { switch (sym) { - case nonterminal(Nonterminal n) : + case nonterminal(Nonterminal n): return Symbol::sort(""); case \start(Nonterminal n) : return Symbol::\start(sort("")); @@ -46,47 +46,58 @@ public Symbol sym2symbol(Sym sym) { case caseInsensitiveLiteral(CaseInsensitiveStringConstant l): return Symbol::cilit(unescapeLiteral(l)); case \parametrized(Nonterminal n, {Sym ","}+ syms) : - return Symbol::\parameterized-sort("",separgs2symbols(syms)); + return Symbol::\parameterized-sort("", separgs2symbols(syms, withLayout=false)); case labeled(Sym s, NonterminalLabel n) : - return Symbol::label("", sym2symbol(s)); + return Symbol::label("", sym2symbol(s, withLayout=withLayout)); case optional(Sym s) : - return Symbol::opt(sym2symbol(s)); + return Symbol::opt(sym2symbol(s, withLayout=withLayout)); case characterClass(Class cc): return cc2ranges(cc); - case parameter(Nonterminal n) : + case parameter(Nonterminal n): return Symbol::\parameter("", adt("Tree", [])); - case empty() : + case empty(): return Symbol::\empty(); - case alternative(Sym first, {Sym "|"}+ alts) : - return alt({sym2symbol(first)} + {sym2symbol(elem) | elem <- alts}); - case iterStar(Sym s) : - return Symbol::\iter-star(sym2symbol(s)); - case iter(Sym s) : - return Symbol::\iter(sym2symbol(s)); - case iterStarSep(Sym s, Sym sep) : - return Symbol::\iter-star-seps(sym2symbol(s), [sym2symbol(sep)]); - case iterSep(Sym s, Sym sep) : - return Symbol::\iter-seps(sym2symbol(s), [sym2symbol(sep)]); - case sequence(Sym first, Sym+ sequence) : - return seq([sym2symbol(first)] + [sym2symbol(elem) | elem <- sequence]); - case startOfLine(Sym s) : - return conditional(sym2symbol(s), {\begin-of-line()}); - case endOfLine(Sym s) : - return conditional(sym2symbol(s), {\end-of-line()}); - case column(Sym s, IntegerLiteral i) : - return conditional(sym2symbol(s), {\at-column(toInt(""))}); - case follow(Sym s, Sym r) : - return conditional(sym2symbol(s), {\follow(sym2symbol(r))}); - case notFollow(Sym s, Sym r) : - return conditional(sym2symbol(s), {\not-follow(sym2symbol(r))}); - case precede(Sym s, Sym r) : - return conditional(sym2symbol(r), {\precede(sym2symbol(s))}); - case notPrecede(Sym s, Sym r) : - return conditional(sym2symbol(r), {\not-precede(sym2symbol(s))}); - case unequal(Sym s, Sym r) : - return conditional(sym2symbol(s), {\delete(sym2symbol(r))}); + case alternative(Sym first, {Sym "|"}+ alts): + return alt({sym2symbol(first, withLayout=withLayout)} + + {sym2symbol(elem, withLayout=withLayout) | elem <- alts}); + case iterStar(Sym s): + return withLayout + ? Symbol::\iter-star-seps(sym2symbol(s, withLayout=withLayout),[defLayout]) + : Symbol::\iter-star(sym2symbol(s, withLayout=withLayout)); + case iter(Sym s): + return withLayout + ? Symbol::\iter-seps(sym2symbol(s, withLayout=withLayout),[defLayout]) + : Symbol::\iter(sym2symbol(s, withLayout=withLayout)); + case iterStarSep(Sym s, Sym sep): + return withLayout + ? Symbol::\iter-star-seps(sym2symbol(s, withLayout=withLayout), [defLayout, sym2symbol(sep), defLayout]) + : Symbol::\iter-star-seps(sym2symbol(s, withLayout=withLayout), [sym2symbol(sep)]); + case iterSep(Sym s, Sym sep): + return withLayout + ? Symbol::\iter-seps(sym2symbol(s, withLayout=withLayout), [defLayout, sym2symbol(sep, withLayout=withLayout), defLayout]) + : Symbol::\iter-seps(sym2symbol(s, withLayout=withLayout), [sym2symbol(sep, withLayout=withLayout)]); + case sequence(Sym first, Sym+ sequence): + return withLayout + ? seq([sym2symbol(first, withLayout=withLayout)] + [sym2symbol(elem, withLayout=withLayout), defLayout | elem <- sequence][..-1]) + : seq([sym2symbol(first, withLayout=withLayout)] + [sym2symbol(elem, withLayout=withLayout) | elem <- sequence]); + case startOfLine(Sym s): + return conditional(sym2symbol(s, withLayout=withLayout), {\begin-of-line()}); + case endOfLine(Sym s): + return conditional(sym2symbol(s, withLayout=withLayout), {\end-of-line()}); + case column(Sym s, IntegerLiteral i): + return conditional(sym2symbol(s, withLayout=withLayout), {\at-column(toInt(""))}); + case follow(Sym s, Sym r): + return conditional(sym2symbol(s, withLayout=withLayout), {\follow(sym2symbol(r, withLayout=withLayout))}); + case notFollow(Sym s, Sym r): + return conditional(sym2symbol(s, withLayout=withLayout), {\not-follow(sym2symbol(r, withLayout=withLayout))}); + case precede(Sym s, Sym r): + return conditional(sym2symbol(r, withLayout=withLayout), {\precede(sym2symbol(s, withLayout=withLayout))}); + case notPrecede(Sym s, Sym r): + return conditional(sym2symbol(r, withLayout=withLayout), {\not-precede(sym2symbol(s, withLayout=withLayout))}); + case unequal(Sym s, Sym r): + return conditional(sym2symbol(s, withLayout=withLayout), {\delete(sym2symbol(r, withLayout=withLayout))}); case except(Sym s, NonterminalLabel n): - return conditional(sym2symbol(s), {\except("")}); + return conditional(sym2symbol(s, withLayout=withLayout), {\except("")}); default: throw "sym2symbol, missed a case "; } @@ -96,8 +107,10 @@ public list[Symbol] args2symbols(Sym* args) { return [sym2symbol(s) | Sym s <- args]; } -public list[Symbol] separgs2symbols({Sym ","}+ args) { - return [sym2symbol(s) | Sym s <- args]; +public list[Symbol] separgs2symbols({Sym ","}+ args, bool withLayout=false) { + return withLayout + ? [sym2symbol(s) | Sym s <- args] + : [sym2symbol(s), layouts("*default*") | Sym s <- args][..-1]; } // flattening rules for regular expressions diff --git a/src/org/rascalmpl/parser/ParserGenerator.java b/src/org/rascalmpl/parser/ParserGenerator.java index 736f71abd16..43671d50692 100644 --- a/src/org/rascalmpl/parser/ParserGenerator.java +++ b/src/org/rascalmpl/parser/ParserGenerator.java @@ -20,6 +20,7 @@ import java.io.PrintWriter; import java.io.Reader; import java.util.Collections; +import java.util.Map; import org.rascalmpl.debug.IRascalMonitor; import org.rascalmpl.exceptions.ImplementationError; @@ -48,8 +49,8 @@ public class ParserGenerator { private final Evaluator evaluator; private final JavaBridge bridge; private final IValueFactory vf; - private static final String packageName = "org.rascalmpl.java.parser.object"; - private static final boolean debug = false; + private static final String packageName = "org.rascalmpl.test.parser"; + private static final boolean debug = true; public ParserGenerator(IRascalMonitor monitor, PrintWriter out, IValueFactory factory, Configuration config) { this.evaluator = ShellEvaluatorFactory.getBasicEvaluator(Reader.nullReader(), out, out, monitor, "$parsergenerator$"); @@ -82,12 +83,13 @@ public IValue diagnoseAmbiguity(IConstructor parseForest) { } } - private void debugOutput(Object thing, String file) { + private void debugOutput(String kind, Object thing, String file) { if (debug) { String classString = thing.toString(); FileOutputStream s = null; try { - System.err.println("Writing parser to " + file); + evaluator.getErrorPrinter().println("\nWriting " + kind + " to " + file); + s = new FileOutputStream(file); s.write(classString.getBytes()); s.flush(); @@ -143,26 +145,32 @@ public String getParserMethodName(IConstructor symbol) { switch (symbol.getName()) { case "start": - return "start__" + getParserMethodName(SymbolAdapter.getStart(symbol)); + return "$start_" + getParserMethodName(SymbolAdapter.getStart(symbol)); case "layouts": - return "layouts_" + SymbolAdapter.getName(symbol); + return "$l_" + SymbolAdapter.getName(symbol); case "sort": + return "$s_" + SymbolAdapter.getName(symbol); case "lex": + return "$l_" + SymbolAdapter.getName(symbol); case "keywords": - return SymbolAdapter.getName(symbol); + return "$k_" + SymbolAdapter.getName(symbol); } synchronized (evaluator) { - return ((IString) evaluator.call((IRascalMonitor) null, "getParserMethodName", symbol)).getValue(); + // TODO we assume here this is a context-free non-terminal for now. + // Later with the syntax role modifiers we can implement parsing for lexical regulars too + Map kwArgs = Map.of("withLayout", vf.bool(true)); + return ((IString) evaluator.call("getParserMethodName", "lang::rascal::grammar::ParserGenerator", kwArgs, symbol)).getValue(); } } /** * Converts the parse tree of a symbol to a UPTR symbol */ - public IConstructor symbolTreeToSymbol(IConstructor symbol) { + public IConstructor symbolTreeToSymbol(IConstructor symbol, boolean withLayout) { synchronized (evaluator) { - return (IConstructor) evaluator.call((IRascalMonitor) null,"sym2symbol", symbol); + Map kws = Map.of("withLayout", vf.bool(withLayout)); + return (IConstructor) evaluator.call("sym2symbol", "lang::rascal::grammar::definition::Symbols", kws, symbol); } } @@ -183,7 +191,7 @@ public Class> getNewParser(IRascalMon profiler.start(); } IConstructor grammar = IRascalValueFactory.getInstance().grammar(definition); - debugOutput(grammar, System.getProperty("java.io.tmpdir") + "/grammar.trm"); + debugOutput("grammar", grammar, System.getProperty("java.io.tmpdir") + "/grammar.trm"); return getNewParser(monitor, loc, name, grammar); } catch (ClassCastException e) { @@ -219,7 +227,7 @@ public Class> getNewParser(IRascalMon synchronized (evaluator) { classString = (IString) evaluator.call(monitor, "newGenerate", vf.string(packageName), vf.string(normName), grammar); } - debugOutput(classString.getValue(), System.getProperty("java.io.tmpdir") + "/parser.java"); + debugOutput("java code", classString.getValue(), "./test/org/rascalmpl/test/parser/" + normName + ".java"); return bridge.compileJava(loc, packageName + "." + normName, classString.getValue()); } catch (ClassCastException e) { @@ -248,7 +256,7 @@ public void writeNewParser(IRascalMonitor monitor, ISourceLocation loc, String n synchronized (evaluator) { classString = (IString) evaluator.call(monitor, "newGenerate", vf.string(packageName), vf.string(normName), grammar); } - debugOutput(classString.getValue(), System.getProperty("java.io.tmpdir") + "/parser.java"); + debugOutput("java code", classString.getValue(), System.getProperty("java.io.tmpdir") + "/parser.java"); bridge.compileJava(loc, packageName + "." + normName, classString.getValue(), out); } catch (ClassCastException e) { diff --git a/src/org/rascalmpl/repl/rascal/RascalLineParser.java b/src/org/rascalmpl/repl/rascal/RascalLineParser.java index 847983b229d..2a18e6e676c 100644 --- a/src/org/rascalmpl/repl/rascal/RascalLineParser.java +++ b/src/org/rascalmpl/repl/rascal/RascalLineParser.java @@ -37,6 +37,7 @@ import org.jline.reader.ParsedLine; import org.jline.reader.Parser; import org.jline.reader.SyntaxError; +import org.rascalmpl.exceptions.ImplementationError; import org.rascalmpl.parser.gtd.exception.ParseError; import org.rascalmpl.values.parsetrees.ITree; import org.rascalmpl.values.parsetrees.TreeAdapter; @@ -264,6 +265,9 @@ private ParsedLine parseFullRascalCommand(String line, int cursor, boolean compl throw new SyntaxError(pe.getBeginLine(), cursor, "Command not recognized"); } } + catch (ImplementationError e) { + throw e; + } catch (Throwable e) { throw new EOFError(1, 0, "Unexpected failure during parsing of the command: " + e.getMessage()); } diff --git a/src/org/rascalmpl/runtime/RascalRuntimeValueFactory.java b/src/org/rascalmpl/runtime/RascalRuntimeValueFactory.java index 73fab13dfed..0574188539f 100644 --- a/src/org/rascalmpl/runtime/RascalRuntimeValueFactory.java +++ b/src/org/rascalmpl/runtime/RascalRuntimeValueFactory.java @@ -239,15 +239,17 @@ protected static String getParserMethodName(IConstructor symbol) { // where many calls into the evaluator/parser are fired in rapid // succession. - switch (symbol.getName()) { + switch (symbol.getName()) { case "start": - return "start__" + getParserMethodName(SymbolAdapter.getStart(symbol)); + return "$start_" + getParserMethodName(SymbolAdapter.getStart(symbol)); case "layouts": - return "layouts_" + SymbolAdapter.getName(symbol); + return "$l_" + SymbolAdapter.getName(symbol); case "sort": + return "$s_" + SymbolAdapter.getName(symbol); case "lex": + return "$l_" + SymbolAdapter.getName(symbol); case "keywords": - return SymbolAdapter.getName(symbol); + return "$k_" + SymbolAdapter.getName(symbol); } return null; diff --git a/src/org/rascalmpl/semantics/dynamic/Import.java b/src/org/rascalmpl/semantics/dynamic/Import.java index a42063cd6fb..530dc76143c 100644 --- a/src/org/rascalmpl/semantics/dynamic/Import.java +++ b/src/org/rascalmpl/semantics/dynamic/Import.java @@ -706,7 +706,8 @@ private static ITree parseFragment(RascalFunctionValueFactory vf, IRascalMonitor Map antiquotes = new HashMap<>(); try { - IConstructor reifiedSym = vf.reifiedType(vf.sym2symbol(symTree), vf.map()); + // TODO: add support for lexical regulars + IConstructor reifiedSym = vf.reifiedType(vf.sym2symbol(symTree, true), vf.map()); SortedMap corrections = new TreeMap<>(); char[] input = replaceAntiQuotesByHoles(vf, lit, antiquotes, corrections); diff --git a/src/org/rascalmpl/values/RascalFunctionValueFactory.java b/src/org/rascalmpl/values/RascalFunctionValueFactory.java index 1ad439fb3fb..aa3c9b4f78e 100644 --- a/src/org/rascalmpl/values/RascalFunctionValueFactory.java +++ b/src/org/rascalmpl/values/RascalFunctionValueFactory.java @@ -242,6 +242,7 @@ public IFunction parser(IValue reifiedGrammar, IBool allowAmbiguity, IInteger ma String name = getParserMethodName(startSort); if (name == null) { + // this method duplication is to avoid loading a parser generator we might not need name = generator.getParserMethodName(startSort); } @@ -254,15 +255,17 @@ protected static String getParserMethodName(IConstructor symbol) { // where many calls into the evaluator/parser are fired in rapid // succession. - switch (symbol.getName()) { + switch (symbol.getName()) { case "start": - return "start__" + getParserMethodName(SymbolAdapter.getStart(symbol)); + return "$start_" + getParserMethodName(SymbolAdapter.getStart(symbol)); case "layouts": - return "layouts_" + SymbolAdapter.getName(symbol); + return "$l_" + SymbolAdapter.getName(symbol); case "sort": + return "$s_" + SymbolAdapter.getName(symbol); case "lex": + return "$l_" + SymbolAdapter.getName(symbol); case "keywords": - return SymbolAdapter.getName(symbol); + return "$k_" + SymbolAdapter.getName(symbol); } return null; @@ -402,13 +405,13 @@ public IString createHole(ITree part, IInteger index) { return result; } - public IConstructor sym2symbol(ITree parsedSym) { + public IConstructor sym2symbol(ITree parsedSym, boolean withLayout) { if ("nonterminal".equals(TreeAdapter.getConstructorName(parsedSym))) { String nonterminalName = TreeAdapter.yield(parsedSym); return constructor(Symbol_Sort, string(nonterminalName)); } - return getParserGenerator().symbolTreeToSymbol(parsedSym); + return getParserGenerator().symbolTreeToSymbol(parsedSym, withLayout); } private static IConstructor checkPreconditions(IValue start, Type reified) { diff --git a/test/org/rascalmpl/test/parser/NonTerminalStarListEmpty.java b/test/org/rascalmpl/test/parser/NonTerminalStarListEmpty.java new file mode 100644 index 00000000000..8539dec1267 --- /dev/null +++ b/test/org/rascalmpl/test/parser/NonTerminalStarListEmpty.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2009-2011 CWI + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + + * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI + * * Arnold Lankamp - Arnold.Lankamp@cwi.nl +*******************************************************************************/ +package org.rascalmpl.test.parser; + +import java.io.IOException; +import java.io.StringReader; + +import org.rascalmpl.parser.gtd.SGTDBF; +import org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener; +import org.rascalmpl.parser.gtd.stack.AbstractStackNode; +import org.rascalmpl.parser.gtd.stack.ListStackNode; +import org.rascalmpl.parser.gtd.stack.LiteralStackNode; +import org.rascalmpl.parser.gtd.stack.NonTerminalStackNode; +import org.rascalmpl.parser.uptr.UPTRNodeFactory; +import io.usethesource.vallang.IConstructor; +import io.usethesource.vallang.ISourceLocation; +import io.usethesource.vallang.IValue; +import io.usethesource.vallang.io.StandardTextReader; + +import org.rascalmpl.values.RascalValueFactory; +import org.rascalmpl.values.ValueFactoryFactory; +import org.rascalmpl.values.parsetrees.ITree; +/* +S ::= A+ +A ::= a +*/ +@SuppressWarnings({"unchecked", "cast"}) +public class NonTerminalStarListEmpty extends SGTDBF implements IParserTest{ + private final static IConstructor SYMBOL_START_S = VF.constructor(RascalValueFactory.Symbol_Sort, VF.string("S")); + private final static IConstructor SYMBOL_A = VF.constructor(RascalValueFactory.Symbol_Sort, VF.string("A")); + private final static IConstructor SYMBOL_STAR_LIST_A = VF.constructor(RascalValueFactory.Symbol_IterStar, SYMBOL_A); + private final static IConstructor SYMBOL_a = VF.constructor(RascalValueFactory.Symbol_Lit, VF.string("a")); + private final static IConstructor SYMBOL_char_a = VF.constructor(RascalValueFactory.Symbol_CharClass, VF.list(VF.constructor(RascalValueFactory.CharRange_Single, VF.integer(97)))); + + private final static IConstructor PROD_S_STARLISTA = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_START_S, VF.list(SYMBOL_STAR_LIST_A), VF.set()); + private final static IConstructor PROD_STARLISTA = VF.constructor(RascalValueFactory.Production_Regular, SYMBOL_STAR_LIST_A); + private final static IConstructor PROD_A_a = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_A, VF.list(SYMBOL_a), VF.set()); + private final static IConstructor PROD_a_a = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_a, VF.list(SYMBOL_char_a), VF.set()); + + private final static AbstractStackNode NONTERMINAL_START_S = new NonTerminalStackNode(AbstractStackNode.START_SYMBOL_ID, 0, "S"); + private final static AbstractStackNode NONTERMINAL_A0 = new NonTerminalStackNode(0, 0, "A"); + private final static AbstractStackNode LIST1 = new ListStackNode(1, 0, PROD_STARLISTA, NONTERMINAL_A0, false); + private final static AbstractStackNode LITERAL_a2 = new LiteralStackNode(2, 0, PROD_a_a, new int[]{'a'}); + + private final static AbstractStackNode[] S_EXPECT_1 = (AbstractStackNode[]) new AbstractStackNode[1]; + static{ + S_EXPECT_1[0] = LIST1; + S_EXPECT_1[0].setProduction(S_EXPECT_1); + S_EXPECT_1[0].setAlternativeProduction(PROD_S_STARLISTA); + } + + private final static AbstractStackNode[] A_EXPECT_1 = (AbstractStackNode[]) new AbstractStackNode[1]; + static{ + A_EXPECT_1[0] = LITERAL_a2; + A_EXPECT_1[0].setProduction(A_EXPECT_1); + A_EXPECT_1[0].setAlternativeProduction(PROD_A_a); + } + + public NonTerminalStarListEmpty(){ + super(); + } + + public AbstractStackNode[] S(){ + return (AbstractStackNode[]) new AbstractStackNode[]{S_EXPECT_1[0]}; + } + + public AbstractStackNode[] A(){ + return (AbstractStackNode[]) new AbstractStackNode[]{A_EXPECT_1[0]}; + } + + public ITree executeParser(){ + return parse(NONTERMINAL_START_S, null, "".toCharArray(), new DefaultNodeFlattener(), new UPTRNodeFactory(true)); + } + + public IValue getExpectedResult() throws IOException{ + String expectedInput = "appl(prod(sort(\"S\"),[\\iter-star(sort(\"A\"))],{}),[appl(regular(\\iter-star(sort(\"A\"))),[])])"; + return new StandardTextReader().read(ValueFactoryFactory.getValueFactory(), RascalValueFactory.uptr, RascalValueFactory.Tree, new StringReader(expectedInput)); + } + + public static void main(String[] args){ + NonTerminalStarListEmpty nrsl = new NonTerminalStarListEmpty(); + IConstructor result = nrsl.executeParser(); + System.out.println(result); + + System.out.println("S(A*()) <- good"); + } +} diff --git a/test/org/rascalmpl/test/parser/TopLevelPlusList.java b/test/org/rascalmpl/test/parser/TopLevelPlusList.java new file mode 100644 index 00000000000..ff3f866cca3 --- /dev/null +++ b/test/org/rascalmpl/test/parser/TopLevelPlusList.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2009-2011 CWI + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + + * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI + * * Arnold Lankamp - Arnold.Lankamp@cwi.nl +*******************************************************************************/ +package org.rascalmpl.test.parser; + +import java.io.IOException; +import java.io.StringReader; + +import org.rascalmpl.parser.gtd.SGTDBF; +import org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener; +import org.rascalmpl.parser.gtd.stack.AbstractStackNode; +import org.rascalmpl.parser.gtd.stack.ListStackNode; +import org.rascalmpl.parser.gtd.stack.LiteralStackNode; +import org.rascalmpl.parser.gtd.stack.NonTerminalStackNode; +import org.rascalmpl.parser.uptr.UPTRNodeFactory; +import io.usethesource.vallang.IConstructor; +import io.usethesource.vallang.ISourceLocation; +import io.usethesource.vallang.IValue; +import io.usethesource.vallang.io.StandardTextReader; + +import org.rascalmpl.values.RascalValueFactory; +import org.rascalmpl.values.ValueFactoryFactory; +import org.rascalmpl.values.parsetrees.ITree; +/* +A+ as start node +A ::= a +*/ +@SuppressWarnings({"unchecked"}) +public class TopLevelPlusList extends SGTDBF implements IParserTest{ + private final static IConstructor SYMBOL_A = VF.constructor(RascalValueFactory.Symbol_Sort, VF.string("A")); + private final static IConstructor SYMBOL_PLUS_LIST_A = VF.constructor(RascalValueFactory.Symbol_Iter, SYMBOL_A); + private final static IConstructor SYMBOL_a = VF.constructor(RascalValueFactory.Symbol_Lit, VF.string("a")); + private final static IConstructor SYMBOL_char_a = VF.constructor(RascalValueFactory.Symbol_CharClass, VF.list(VF.constructor(RascalValueFactory.CharRange_Single, VF.integer(97)))); + + private final static IConstructor PROD_PLUSLISTA = VF.constructor(RascalValueFactory.Production_Regular, SYMBOL_PLUS_LIST_A); + private final static IConstructor PROD_A_a = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_A, VF.list(SYMBOL_a), VF.set()); + private final static IConstructor PROD_a_a = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_a, VF.list(SYMBOL_char_a), VF.set()); + + private final static AbstractStackNode NONTERMINAL_A0 = new NonTerminalStackNode(0, 0, "A"); + private final static AbstractStackNode LIST1 = new ListStackNode(1, 0, PROD_PLUSLISTA, NONTERMINAL_A0, true); + private final static AbstractStackNode LITERAL_a2 = new LiteralStackNode(2, 0, PROD_a_a, new int[]{'a'}); + + + private final static AbstractStackNode[] A_EXPECT_1 = (AbstractStackNode[]) new AbstractStackNode[1]; + static{ + A_EXPECT_1[0] = LITERAL_a2; + A_EXPECT_1[0].setProduction(A_EXPECT_1); + A_EXPECT_1[0].setAlternativeProduction(PROD_A_a); + } + + public TopLevelPlusList(){ + super(); + } + + + public AbstractStackNode[] A(){ + return (AbstractStackNode[]) new AbstractStackNode[]{A_EXPECT_1[0]}; + } + + public ITree executeParser(){ + return parse(LIST1, null, "aaa".toCharArray(), new DefaultNodeFlattener(), new UPTRNodeFactory(true)); + } + + public IValue getExpectedResult() throws IOException{ + String expectedInput = "appl(regular(iter(sort(\"A\"))),[appl(prod(sort(\"A\"),[lit(\"a\")],{}),[appl(prod(lit(\"a\"),[\\char-class([single(97)])],{}),[char(97)])]),appl(prod(sort(\"A\"),[lit(\"a\")],{}),[appl(prod(lit(\"a\"),[\\char-class([single(97)])],{}),[char(97)])]),appl(prod(sort(\"A\"),[lit(\"a\")],{}),[appl(prod(lit(\"a\"),[\\char-class([single(97)])],{}),[char(97)])])])"; + return new StandardTextReader().read(ValueFactoryFactory.getValueFactory(), RascalValueFactory.uptr, RascalValueFactory.Tree, new StringReader(expectedInput)); + } + + public static void main(String[] args){ + TopLevelPlusList nrpl = new TopLevelPlusList(); + IConstructor result = nrpl.executeParser(); + System.out.println(result); + + System.out.println("A+(A(a),A(a),A(a)) <- good"); + } +} diff --git a/test/org/rascalmpl/test/parser/TopLevelStarList.java b/test/org/rascalmpl/test/parser/TopLevelStarList.java new file mode 100644 index 00000000000..b941ea0f2d1 --- /dev/null +++ b/test/org/rascalmpl/test/parser/TopLevelStarList.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2009-2011 CWI + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + + * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI + * * Arnold Lankamp - Arnold.Lankamp@cwi.nl +*******************************************************************************/ +package org.rascalmpl.test.parser; + +import java.io.IOException; +import java.io.StringReader; + +import org.rascalmpl.parser.gtd.SGTDBF; +import org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener; +import org.rascalmpl.parser.gtd.stack.AbstractStackNode; +import org.rascalmpl.parser.gtd.stack.ListStackNode; +import org.rascalmpl.parser.gtd.stack.LiteralStackNode; +import org.rascalmpl.parser.gtd.stack.NonTerminalStackNode; +import org.rascalmpl.parser.uptr.UPTRNodeFactory; +import io.usethesource.vallang.IConstructor; +import io.usethesource.vallang.ISourceLocation; +import io.usethesource.vallang.IValue; +import io.usethesource.vallang.io.StandardTextReader; + +import org.rascalmpl.values.RascalValueFactory; +import org.rascalmpl.values.ValueFactoryFactory; +import org.rascalmpl.values.parsetrees.ITree; +/* +A+ as start node +A ::= a +*/ +@SuppressWarnings({"unchecked"}) +public class TopLevelStarList extends SGTDBF implements IParserTest{ + private final static IConstructor SYMBOL_A = VF.constructor(RascalValueFactory.Symbol_Sort, VF.string("A")); + private final static IConstructor SYMBOL_STAR_LIST_A = VF.constructor(RascalValueFactory.Symbol_Iter, SYMBOL_A); + private final static IConstructor SYMBOL_a = VF.constructor(RascalValueFactory.Symbol_Lit, VF.string("a")); + private final static IConstructor SYMBOL_char_a = VF.constructor(RascalValueFactory.Symbol_CharClass, VF.list(VF.constructor(RascalValueFactory.CharRange_Single, VF.integer(97)))); + + private final static IConstructor PROD_STARLISTA = VF.constructor(RascalValueFactory.Production_Regular, SYMBOL_STAR_LIST_A); + private final static IConstructor PROD_A_a = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_A, VF.list(SYMBOL_a), VF.set()); + private final static IConstructor PROD_a_a = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_a, VF.list(SYMBOL_char_a), VF.set()); + + private final static AbstractStackNode NONTERMINAL_A0 = new NonTerminalStackNode(0, 0, "A"); + private final static AbstractStackNode LIST1 = new ListStackNode(1, 0, PROD_STARLISTA, NONTERMINAL_A0, true); + private final static AbstractStackNode LITERAL_a2 = new LiteralStackNode(2, 0, PROD_a_a, new int[]{'a'}); + + + private final static AbstractStackNode[] A_EXPECT_1 = (AbstractStackNode[]) new AbstractStackNode[1]; + static{ + A_EXPECT_1[0] = LITERAL_a2; + A_EXPECT_1[0].setProduction(A_EXPECT_1); + A_EXPECT_1[0].setAlternativeProduction(PROD_A_a); + } + + public TopLevelStarList(){ + super(); + } + + + public AbstractStackNode[] A(){ + return (AbstractStackNode[]) new AbstractStackNode[]{A_EXPECT_1[0]}; + } + + public ITree executeParser(){ + return parse(LIST1, null, "aaa".toCharArray(), new DefaultNodeFlattener(), new UPTRNodeFactory(true)); + } + + public IValue getExpectedResult() throws IOException{ + String expectedInput = "appl(regular(\\iter-star(sort(\"A\"))),[appl(prod(sort(\"A\"),[lit(\"a\")],{}),[appl(prod(lit(\"a\"),[\\char-class([single(97)])],{}),[char(97)])]),appl(prod(sort(\"A\"),[lit(\"a\")],{}),[appl(prod(lit(\"a\"),[\\char-class([single(97)])],{}),[char(97)])]),appl(prod(sort(\"A\"),[lit(\"a\")],{}),[appl(prod(lit(\"a\"),[\\char-class([single(97)])],{}),[char(97)])])])"; + return new StandardTextReader().read(ValueFactoryFactory.getValueFactory(), RascalValueFactory.uptr, RascalValueFactory.Tree, new StringReader(expectedInput)); + } + + public static void main(String[] args){ + TopLevelStarList nrpl = new TopLevelStarList(); + IConstructor result = nrpl.executeParser(); + System.out.println(result); + + System.out.println("A+(A(a),A(a),A(a)) <- good"); + } +} diff --git a/test/org/rascalmpl/test/parser/TopLevelStarListEmpty.java b/test/org/rascalmpl/test/parser/TopLevelStarListEmpty.java new file mode 100644 index 00000000000..9c133eb3019 --- /dev/null +++ b/test/org/rascalmpl/test/parser/TopLevelStarListEmpty.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2009-2011 CWI + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + + * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI + * * Arnold Lankamp - Arnold.Lankamp@cwi.nl +*******************************************************************************/ +package org.rascalmpl.test.parser; + +import java.io.IOException; +import java.io.StringReader; + +import org.rascalmpl.parser.gtd.SGTDBF; +import org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener; +import org.rascalmpl.parser.gtd.stack.AbstractStackNode; +import org.rascalmpl.parser.gtd.stack.ListStackNode; +import org.rascalmpl.parser.gtd.stack.LiteralStackNode; +import org.rascalmpl.parser.gtd.stack.NonTerminalStackNode; +import org.rascalmpl.parser.uptr.UPTRNodeFactory; +import io.usethesource.vallang.IConstructor; +import io.usethesource.vallang.ISourceLocation; +import io.usethesource.vallang.IValue; +import io.usethesource.vallang.io.StandardTextReader; + +import org.rascalmpl.values.RascalValueFactory; +import org.rascalmpl.values.ValueFactoryFactory; +import org.rascalmpl.values.parsetrees.ITree; +/* +A+ as start node +A ::= a +*/ +@SuppressWarnings({"unchecked"}) +public class TopLevelStarListEmpty extends SGTDBF implements IParserTest{ + private final static IConstructor SYMBOL_A = VF.constructor(RascalValueFactory.Symbol_Sort, VF.string("A")); + private final static IConstructor SYMBOL_STAR_LIST_A = VF.constructor(RascalValueFactory.Symbol_IterStar, SYMBOL_A); + private final static IConstructor SYMBOL_a = VF.constructor(RascalValueFactory.Symbol_Lit, VF.string("a")); + private final static IConstructor SYMBOL_char_a = VF.constructor(RascalValueFactory.Symbol_CharClass, VF.list(VF.constructor(RascalValueFactory.CharRange_Single, VF.integer(97)))); + + private final static IConstructor PROD_STARLISTA = VF.constructor(RascalValueFactory.Production_Regular, SYMBOL_STAR_LIST_A); + private final static IConstructor PROD_A_a = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_A, VF.list(SYMBOL_a), VF.set()); + private final static IConstructor PROD_a_a = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_a, VF.list(SYMBOL_char_a), VF.set()); + + private final static AbstractStackNode NONTERMINAL_A0 = new NonTerminalStackNode(0, 0, "A"); + private final static AbstractStackNode LIST1 = new ListStackNode(1, 0, PROD_STARLISTA, NONTERMINAL_A0, false); + private final static AbstractStackNode LITERAL_a2 = new LiteralStackNode(2, 0, PROD_a_a, new int[]{'a'}); + + + private final static AbstractStackNode[] A_EXPECT_1 = (AbstractStackNode[]) new AbstractStackNode[1]; + static{ + A_EXPECT_1[0] = LITERAL_a2; + A_EXPECT_1[0].setProduction(A_EXPECT_1); + A_EXPECT_1[0].setAlternativeProduction(PROD_A_a); + } + + public TopLevelStarListEmpty(){ + super(); + } + + + public AbstractStackNode[] A(){ + return (AbstractStackNode[]) new AbstractStackNode[]{A_EXPECT_1[0]}; + } + + public ITree executeParser(){ + return parse(LIST1, null, "".toCharArray(), new DefaultNodeFlattener(), new UPTRNodeFactory(true)); + } + + public IValue getExpectedResult() throws IOException{ + String expectedInput = "appl(regular(iter(sort(\"A\"))),[])"; + return new StandardTextReader().read(ValueFactoryFactory.getValueFactory(), RascalValueFactory.uptr, RascalValueFactory.Tree, new StringReader(expectedInput)); + } + + public static void main(String[] args){ + TopLevelStarListEmpty nrpl = new TopLevelStarListEmpty(); + IConstructor result = nrpl.executeParser(); + System.out.println(result); + + System.out.println("A*() <- good"); + } +}