use of suite.ebnf.Ebnf.Ast in project suite by stupidsing.
the class TopDownParse method parse.
public Ast parse(String entity, String s) {
Parse parse = new Parse(s);
Ast node = parse.parse(0, build(new Grammar(GrammarType.ENTITY, entity)));
if (node != null)
return node;
else {
IntIntPair pos = parse.findPosition(parse.errorPosition);
return Fail.t("syntax error for entity " + parse.errorEntity + " at " + pos);
}
}
use of suite.ebnf.Ebnf.Ast in project suite by stupidsing.
the class Dump method prettyPrint.
private void prettyPrint(Ast ast, String indent) throws IOException {
String entity0 = ast.entity;
List<Ast> children;
while ((children = ast.children).size() == 1) ast = children.get(0);
if (children.size() != 1) {
String indent1 = indent + " ";
String entity1 = ast.entity;
int start = ast.getStart();
int end = ast.getEnd();
w.write(indent + entity0);
if (!String_.equals(entity0, entity1))
w.write(".." + entity1);
w.write("@" + start + "-" + end);
if (children.isEmpty())
w.write("[" + in.substring(start, end) + "]");
w.write("\n");
for (Ast child : children) prettyPrint(child, indent1);
} else
prettyPrint(children.get(0), indent);
}
use of suite.ebnf.Ebnf.Ast in project suite by stupidsing.
the class LrParse method parse.
private Ast parse(Source<Ast> tokens, State state) {
Deque<Pair<Ast, State>> stack = new ArrayDeque<>();
Ast token = tokens.source();
while (true) {
String lookahead = token != null ? token.entity : "EOF";
Pair<State, Reduce> sr = shift(stack, state, lookahead);
if (sr.t0 != null) {
// shift
stack.push(Pair.of(token, state));
state = sr.t0;
token = tokens.source();
} else {
// reduce
Reduce reduce = sr.t1;
IList<Ast> nodes = IList.end();
for (int i = 0; i < reduce.n(); i++) {
Pair<Ast, State> ns = stack.pop();
nodes = IList.cons(ns.t0, nodes);
state = ns.t1;
}
Ast token1 = new Ast(reduce.name(), 0, 0, Read.from(nodes).toList());
if (rootEntity.equals(reduce.name()) && stack.size() == 0 && token == null)
return token1;
// force shift after reduce
stack.push(Pair.of(token1, state));
state = shift(stack, state, token1.entity).t0;
}
}
}
use of suite.ebnf.Ebnf.Ast in project suite by stupidsing.
the class P0CrudeScript method parse.
public Funp parse(String in) {
// "{ return 1 + 2 * 3; }"
var ebnf = ex(() -> new Ebnf(new FileReader("src/main/ebnf/crude-script.ebnf")));
var ast = ebnf.parse("crude-script", in);
var node = new Object() {
private Node node(Ast ast) {
var entity = ast.entity;
var children = ast.children;
var atom = Atom.of(entity);
Node node;
if (entity.startsWith("<"))
node = new Str(in.substring(ast.start, ast.end));
else
node = Read.from(children).reverse().<Node>fold(Atom.NIL, (n, c) -> Tree.ofAnd(node(c), n));
return TreeTuple.of(atom, node);
}
}.node(ast);
return new Object() {
private Funp crudeScript(Node node) {
return new //
SwitchNode<Funp>(//
node).match("crude-script (.0,)", a -> {
return stmt(a);
}).nonNullResult();
}
private Funp stmt(Node node) {
return new //
SwitchNode<Funp>(//
node).match("statement (expression (.0,),)", a -> {
return expr(a);
}).match("statement (statement-return (.0,),)", a -> {
return expr(a);
}).match("statement1 (.0,)", a -> {
return stmt(a);
}).match("statement-block (statement-let (bind (<IDENTIFIER> .0,), .1,), .2)", (a, b, c) -> {
return FunpDefine.of(Str.str(a), expr(b), stmt(c), Fdt.L_MONO);
}).match("statement-block (.0,)", a -> {
return stmt(a);
}).match("statement-for (.0, .1, .2, .3,)", (a, b, c, d) -> {
return expr(a);
}).match("statement-if (.0, .1, .2,)", (a, b, c) -> {
return FunpIf.of(expr(a), stmt(b), stmt(c));
}).match("statement-while (.0, .1,)", (a, b) -> {
return expr(b);
}).nonNullResult();
}
private Funp expr(Node node) {
return new //
SwitchNode<Funp>(//
node).match("<IDENTIFIER> .0", s -> {
return FunpVariable.of(Str.str(s));
}).match("<INTEGER_LITERAL> .0", s -> {
return FunpNumber.ofNumber(Integer.valueOf(Str.str(s)));
}).match("<STRING_LITERAL> .0", s -> {
return fail();
}).match("constant (.0,)", a -> {
return expr(a);
}).match("expression (.0,)", a -> {
return expr(a);
}).match("expression-add (.0, .1)", (a, b) -> {
return Tree.read(b).fold(expr(a), (f, c) -> FunpTree.of(FunpOp.PLUS__, f, expr(c)));
}).match("expression-and (.0,)", a -> {
return expr(a);
}).match("expression-as (.0,)", a -> {
return expr(a);
}).match("expression-assign (.0, .1)", (a, b) -> {
return expr(a);
}).matchArray("expression-array .0", m -> {
return FunpArray.of(Read.from(m).map(this::expr).toList());
}).match("expression-bool-and (.0, .1)", (a, b) -> {
return Tree.read(b).fold(expr(a), (f, c) -> FunpTree.of(FunpOp.BIGAND, f, expr(c)));
}).match("expression-bool-not (.0,)", a -> {
return expr(a);
}).match("expression-bool-or (.0, .1)", (a, b) -> {
return Tree.read(b).fold(expr(a), (f, c) -> FunpTree.of(FunpOp.BIGOR_, f, expr(c)));
}).match("expression-compare (.0,)", a -> {
return expr(a);
}).match("expression-dict .0", a -> {
var list = //
Tree.read(//
a).chunk(//
2).map(//
o -> o.toFixie().map((k, v) -> Pair.of(Str.str(k), expr(v)))).toList();
return FunpStruct.of(list);
}).match("expression-div (.0, .1)", (a, b) -> {
return //
Tree.read(//
b).chunk(//
2).fold(expr(a), (f, o) -> o.toFixie().map((op, d) -> {
return new //
SwitchNode<Funp>(//
op).matchArray("'/'", m_ -> {
return FunpTree.of(FunpOp.DIVIDE, f, expr(d));
}).matchArray("'%'", m_ -> {
return FunpTree.of(FunpOp.MODULO, f, expr(d));
}).nonNullResult();
}));
}).match("expression-invoke (.0, .1)", (a, b) -> {
return Tree.read(b).fold(expr(a), (f, c) -> FunpApply.of(f, expr(c)));
}).match("expression-mul (.0, .1)", (a, b) -> {
return Tree.read(b).fold(expr(a), (f, c) -> FunpTree.of(FunpOp.MULT__, f, expr(c)));
}).match("expression-not (.0,)", a -> {
return expr(a);
}).match("expression-lambda (bind (<IDENTIFIER> (.0,),), expression (.1,),)", (a, b) -> {
return FunpLambda.of(Str.str(a), expr(b));
}).match("expression-lambda (bind (<IDENTIFIER> (.0,),), statement-block (.1),)", (a, b) -> {
return FunpLambda.of(Str.str(a), stmt(b));
}).match("expression-obj (.0,)", a -> {
return expr(a);
}).match("expression-or (.0,)", a -> {
return expr(a);
}).match("expression-pp .0", a -> {
var pat0 = Suite.pattern("op-inc-dec ('++' (),)");
var pat1 = Suite.pattern("op-inc-dec ('--' (),)");
var list = Tree.read(a).toList();
Obj_Int<Node> f = op -> pat0.match(op) != null ? 1 : pat1.match(op) != null ? -1 : 0;
int s = 0, e = list.size() - 1, c;
int pre_ = 0, post = 0;
while ((c = f.apply(list.get(s))) != 0) {
pre_ += c;
s++;
}
while ((c = f.apply(list.get(e))) != 0) {
post += c;
e--;
}
var e0 = expr(list.get(s));
var ref0 = FunpReference.of(e0);
var e1 = pre_ == 0 ? e0 : FunpDoAssignRef.of(ref0, FunpTree.of(FunpOp.PLUS__, e0, FunpNumber.ofNumber(pre_)), e0);
var e2 = post == 0 ? e1 : Fail.<Funp>fail();
return s == e ? e2 : fail();
}).match("expression-prop (.0, .1)", (a, b) -> {
return //
Tree.read(//
b).chunk(//
2).fold(expr(a), (f, o) -> o.toFixie().map((k, v) -> {
return new //
SwitchNode<Funp>(//
k).matchArray("'.'", m_ -> {
return FunpField.of(FunpReference.of(f), Str.str(v));
}).matchArray("'['", m_ -> {
return FunpIndex.of(FunpReference.of(f), expr(v));
}).matchArray("'('", m_ -> {
return FunpApply.of(expr(v), f);
}).nonNullResult();
}));
}).match("expression-shift (.0,)", a -> {
return expr(a);
}).match("expression-sub (.0,)", a -> {
return expr(a);
}).match("expression-tuple .0", a -> {
var list = new ArrayList<Pair<String, Funp>>();
var i = 0;
for (var child : Tree.read(a)) list.add(Pair.of("t" + i++, expr(child)));
return FunpStruct.of(list);
}).match("expression-xor (.0,)", a -> {
return expr(a);
}).nonNullResult();
}
}.crudeScript(node);
}
Aggregations