Improve ast classes and visitor.

This commit is contained in:
James Roseborough
2010-06-24 05:15:41 +00:00
parent f50d7eb7d3
commit bce5c5a5b7
11 changed files with 275 additions and 236 deletions

View File

@@ -47,16 +47,16 @@ public class LuaParser {
parser.Chunk(); parser.Chunk();
} }
private static VarExp assertvarexp(PrimaryExp pe) throws ParseException { private static Exp.VarExp assertvarexp(Exp.PrimaryExp pe) throws ParseException {
if (!pe.isvarexp()) if (!pe.isvarexp())
throw new ParseException("exptected variable"); throw new ParseException("exptected variable");
return (VarExp) pe; return (Exp.VarExp) pe;
} }
private static FuncCall assertfunccall(PrimaryExp pe) throws ParseException { private static Exp.FuncCall assertfunccall(Exp.PrimaryExp pe) throws ParseException {
if (!pe.isfunccall()) if (!pe.isfunccall())
throw new ParseException("expected function call"); throw new ParseException("expected function call");
return (FuncCall) pe; return (Exp.FuncCall) pe;
} }
} }
@@ -230,7 +230,7 @@ Stat LastStat():
Stat ExprStat(): Stat ExprStat():
{ {
PrimaryExp pe; Exp.PrimaryExp pe;
Stat as=null; Stat as=null;
} }
{ {
@@ -238,20 +238,20 @@ Stat ExprStat():
{ return as==null? Stat.functioncall(assertfunccall(pe)): as; } { return as==null? Stat.functioncall(assertfunccall(pe)): as; }
} }
Stat Assign(VarExp v0): Stat Assign(Exp.VarExp v0):
{ {
List<VarExp> vl = new ArrayList<VarExp>(); List<Exp.VarExp> vl = new ArrayList<Exp.VarExp>();
vl.add(v0); vl.add(v0);
VarExp ve; Exp.VarExp ve;
List<Exp> el; List<Exp> el;
} }
{ {
( "," ve=VarExp() { vl.add(ve); } )* "=" el=ExpList() { return Stat.assignment(vl,el); } ( "," ve=VarExp() { vl.add(ve); } )* "=" el=ExpList() { return Stat.assignment(vl,el); }
} }
VarExp VarExp(): Exp.VarExp VarExp():
{ {
PrimaryExp pe; Exp.PrimaryExp pe;
} }
{ {
pe=PrimaryExp() { return assertvarexp(pe); } pe=PrimaryExp() { return assertvarexp(pe); }
@@ -269,36 +269,35 @@ FuncName FuncName():
{return fn;} {return fn;}
} }
PrimaryExp PrefixExp(): Exp.PrimaryExp PrefixExp():
{ {
Token n; Token n;
Exp e; Exp e;
} }
{ {
n=<NAME> { return PrimaryExp.nameprefix(n.image); } n=<NAME> { return Exp.nameprefix(n.image); }
| "(" e=Exp() ")" { return PrimaryExp.parensprefix(e); } | "(" e=Exp() ")" { return Exp.parensprefix(e); }
} }
PrimaryExp PrimaryExp(): Exp.PrimaryExp PrimaryExp():
{ {
PrimaryExp pe; Exp.PrimaryExp pe;
PostfixOp po;
} }
{ {
pe=PrefixExp() ( LOOKAHEAD(2) po=PostfixOp() {pe=pe.append(po);} )* { return pe; } pe=PrefixExp() ( LOOKAHEAD(2) pe=PostfixOp(pe) )* { return pe; }
} }
PostfixOp PostfixOp(): Exp.PrimaryExp PostfixOp(Exp.PrimaryExp lhs):
{ {
Token n; Token n;
Exp e; Exp e;
FuncArgs a; FuncArgs a;
} }
{ {
"." n=<NAME> { return PostfixOp.fieldop(n.image); } "." n=<NAME> { return Exp.fieldop(lhs, n.image); }
| "[" e=Exp() "]" { return PostfixOp.indexop(e); } | "[" e=Exp() "]" { return Exp.indexop(lhs, e); }
| ":" n=<NAME> a=FuncArgs() { return PostfixOp.methodop(n.image,a); } | ":" n=<NAME> a=FuncArgs() { return Exp.methodop(lhs, n.image,a); }
| a=FuncArgs() { return PostfixOp.functionop(a); } | a=FuncArgs() { return Exp.functionop(lhs, a); }
} }
FuncArgs FuncArgs(): FuncArgs FuncArgs():
@@ -403,30 +402,30 @@ ParList ParList():
TableConstructor TableConstructor(): TableConstructor TableConstructor():
{ {
TableConstructor tc = new TableConstructor(); TableConstructor tc = new TableConstructor();
List<Field> fl = null; List<TableField> fl = null;
} }
{ {
"{" ( fl=FieldList() {tc.fields=fl;} )? "}" { return tc; } "{" ( fl=FieldList() {tc.fields=fl;} )? "}" { return tc; }
} }
List<Field> FieldList(): List<TableField> FieldList():
{ {
List<Field> fl = new ArrayList<Field>(); List<TableField> fl = new ArrayList<TableField>();
Field f; TableField f;
} }
{ {
f=Field() {fl.add(f);} (LOOKAHEAD(2) FieldSep() f=Field() {fl.add(f);})* (FieldSep())? { return fl; } f=Field() {fl.add(f);} (LOOKAHEAD(2) FieldSep() f=Field() {fl.add(f);})* (FieldSep())? { return fl; }
} }
Field Field(): TableField Field():
{ {
Token name; Token name;
Exp exp,rhs; Exp exp,rhs;
} }
{ {
"[" exp=Exp() "]" "=" rhs=Exp() { return Field.keyedField(exp,rhs); } "[" exp=Exp() "]" "=" rhs=Exp() { return TableField.keyedField(exp,rhs); }
| LOOKAHEAD(2) name=<NAME> "=" rhs=Exp() { return Field.namedField(name.image,rhs); } | LOOKAHEAD(2) name=<NAME> "=" rhs=Exp() { return TableField.namedField(name.image,rhs); }
| rhs=Exp() { return Field.listField(rhs); } | rhs=Exp() { return TableField.listField(rhs); }
} }
void FieldSep(): void FieldSep():

View File

@@ -51,6 +51,142 @@ public class Exp {
return new AnonFuncDef(funcbody); return new AnonFuncDef(funcbody);
} }
/** foo */
public static NameExp nameprefix(String name) {
return new NameExp(name);
}
/** ( foo.bar ) */
public static ParensExp parensprefix(Exp exp) {
return new ParensExp(exp);
}
/** foo[exp] */
public static IndexExp indexop(PrimaryExp lhs, Exp exp) {
return new IndexExp(lhs, exp);
}
/** foo.bar */
public static FieldExp fieldop(PrimaryExp lhs, String name) {
return new FieldExp(lhs, name);
}
/** foo(2,3) */
public static FuncCall functionop(PrimaryExp lhs, FuncArgs args) {
return new FuncCall(lhs, args);
}
/** foo:bar(4,5) */
public static MethodCall methodop(PrimaryExp lhs, String name, FuncArgs args) {
return new MethodCall(lhs, name, args);
}
public boolean isvarexp() {
return false;
}
public boolean isfunccall() {
return false;
}
abstract public static class PrimaryExp extends Exp {
public boolean isvarexp() {
return false;
}
public boolean isfunccall() {
return false;
}
}
abstract public static class VarExp extends PrimaryExp {
public boolean isvarexp() {
return true;
}
}
public static class NameExp extends VarExp {
public final Name name;
public NameExp(String name) {
this.name = new Name(name);
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public static class ParensExp extends PrimaryExp {
public final Exp exp;
public ParensExp(Exp exp) {
this.exp = exp;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public static class FieldExp extends VarExp {
public final PrimaryExp lhs;
public final Name name;
public FieldExp(PrimaryExp lhs, String name) {
this.lhs = lhs;
this.name = new Name(name);
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public static class IndexExp extends VarExp {
public final PrimaryExp lhs;
public final Exp exp;
public IndexExp(PrimaryExp lhs, Exp exp) {
this.lhs = lhs;
this.exp = exp;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public static class FuncCall extends PrimaryExp {
public final PrimaryExp lhs;
public final FuncArgs args;
public FuncCall(PrimaryExp lhs, FuncArgs args) {
this.lhs = lhs;
this.args = args;
}
public boolean isfunccall() {
return true;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public static class MethodCall extends FuncCall {
public final String name;
public MethodCall(PrimaryExp lhs, String name, FuncArgs args) {
super(lhs, args);
this.name = new String(name);
}
public boolean isfunccall() {
return true;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public static class Constant extends Exp { public static class Constant extends Exp {
public final LuaValue value; public final LuaValue value;
public Constant(LuaValue value) { public Constant(LuaValue value) {

View File

@@ -1,30 +0,0 @@
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.ast;
public class FuncCall extends PrimaryExp {
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,61 +0,0 @@
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.ast;
public class PostfixOp {
/** foo[exp] */
public static PostfixOp indexop(Exp e) {
// TODO Auto-generated method stub
return null;
}
/** foo.name */
public static PostfixOp fieldop(String name) {
// TODO Auto-generated method stub
return null;
}
/** foo:name(args) */
public static PostfixOp methodop(String name, FuncArgs args) {
// TODO Auto-generated method stub
return null;
}
/** foo(args) */
public static PostfixOp functionop(FuncArgs a) {
// TODO Auto-generated method stub
return null;
}
public boolean isvarop() {
return false;
}
public boolean isfunccall() {
return false;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,57 +0,0 @@
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.ast;
import java.util.ArrayList;
import java.util.List;
public class PrimaryExp extends Exp {
List<PostfixOp> ops;
public static PrimaryExp nameprefix(String image) {
return null;
}
public static PrimaryExp parensprefix(Exp e) {
return null;
}
public PrimaryExp append(PostfixOp op) {
if ( ops == null )
ops = new ArrayList<PostfixOp>();
ops.add( op );
return this;
}
public boolean isvarexp() {
return ops != null && ops.get(ops.size()-1).isvarop();
}
public boolean isfunccall() {
return ops != null && ops.get(ops.size()-1).isfunccall();
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

View File

@@ -47,11 +47,11 @@ public class Stat {
return new Return(exps); return new Return(exps);
} }
public static Stat assignment(List<VarExp> vars, List<Exp> exps) { public static Stat assignment(List<Exp.VarExp> vars, List<Exp> exps) {
return new Assign(vars,exps); return new Assign(vars,exps);
} }
public static Stat functioncall(FuncCall funccall) { public static Stat functioncall(Exp.FuncCall funccall) {
return new FuncCallStat(funccall); return new FuncCallStat(funccall);
} }
@@ -80,10 +80,10 @@ public class Stat {
} }
public static class Assign extends Stat { public static class Assign extends Stat {
public final List<VarExp> vars; public final List<Exp.VarExp> vars;
public final List<Exp> exps; public final List<Exp> exps;
public Assign(List<VarExp> vars, List<Exp> exps) { public Assign(List<Exp.VarExp> vars, List<Exp> exps) {
this.vars = vars; this.vars = vars;
this.exps = exps; this.exps = exps;
} }
@@ -136,8 +136,8 @@ public class Stat {
} }
public static class FuncCallStat extends Stat { public static class FuncCallStat extends Stat {
public final FuncCall funccall; public final Exp.FuncCall funccall;
public FuncCallStat(FuncCall funccall) { public FuncCallStat(Exp.FuncCall funccall) {
this.funccall = funccall; this.funccall = funccall;
} }

View File

@@ -57,7 +57,7 @@ public class Str {
try { try {
return s.getBytes("UTF8"); return s.getBytes("UTF8");
} catch ( Exception e ) { } catch ( Exception e ) {
throw new RuntimeException("utf8 nto found: "+e); throw new RuntimeException("utf8 not found: "+e);
} }
} }
} }

View File

@@ -24,7 +24,7 @@ package org.luaj.vm2.ast;
import java.util.List; import java.util.List;
public class TableConstructor extends Exp { public class TableConstructor extends Exp {
public List<Field> fields; public List<TableField> fields;
public void accept(Visitor visitor) { public void accept(Visitor visitor) {
visitor.visit(this); visitor.visit(this);

View File

@@ -21,28 +21,28 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2.ast; package org.luaj.vm2.ast;
public class Field { public class TableField {
public final Exp index; public final Exp index;
public final String name; public final String name;
public final Exp rhs; public final Exp rhs;
public Field(Exp index, String name, Exp rhs) { public TableField(Exp index, String name, Exp rhs) {
this.index = index; this.index = index;
this.name = name; this.name = name;
this.rhs = rhs; this.rhs = rhs;
} }
public static Field keyedField(Exp index, Exp rhs) { public static TableField keyedField(Exp index, Exp rhs) {
return new Field(index, null, rhs); return new TableField(index, null, rhs);
} }
public static Field namedField(String name, Exp rhs) { public static TableField namedField(String name, Exp rhs) {
return new Field(null, name, rhs); return new TableField(null, name, rhs);
} }
public static Field listField(Exp rhs) { public static TableField listField(Exp rhs) {
return new Field(null, null, rhs); return new TableField(null, null, rhs);
} }
public void accept(Visitor visitor) { public void accept(Visitor visitor) {

View File

@@ -1,28 +0,0 @@
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.ast;
public class VarExp extends PrimaryExp {
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,64 +1,144 @@
package org.luaj.vm2.ast; package org.luaj.vm2.ast;
import java.util.List;
abstract public class Visitor { abstract public class Visitor {
public void visit(Chunk chunk) { public void visit(Chunk chunk) {
chunk.block.accept(this); chunk.block.accept(this);
}; };
public void visit(Block block) { public void visit(Block block) {
if ( block.stats != null ) if ( block.stats != null )
for ( Stat s : block.stats ) for ( Stat s: block.stats )
s.accept( this ); s.accept(this);
}; };
public void visit(Stat.Assign assign) { public void visit(Stat.Assign stat) {
visitVars(stat.vars);
visitExps(stat.exps);
} }
public void visit(Stat.Break breakstat) { public void visit(Stat.Break breakstat) {
} }
public void visit(Stat.FuncCallStat stat) { public void visit(Stat.FuncCallStat stat) {
stat.funccall.accept(this);
} }
public void visit(Stat.FuncDef stat) { public void visit(Stat.FuncDef stat) {
stat.body.accept(this);
} }
public void visit(Stat.GenericFor stat) { public void visit(Stat.GenericFor stat) {
visitNames(stat.names);
visitExps(stat.exps);
stat.block.accept(this);
} }
public void visit(Stat.IfThenElse stat) { public void visit(Stat.IfThenElse stat) {
stat.ifexp.accept(this);
stat.ifblock.accept(this);
for ( int i=0, n=stat.elseifblocks.size(); i<n; i++ ) {
stat.elseifexps.get(i).accept(this);
stat.elseifblocks.get(i).accept(this);
}
visit( stat.elseblock );
} }
public void visit(Stat.LocalAssign stat) { public void visit(Stat.LocalAssign stat) {
visitNames(stat.names);
visitExps(stat.values);
} }
public void visit(Stat.LocalFuncDef stat) { public void visit(Stat.LocalFuncDef stat) {
visit(stat.name);
stat.body.accept(this);
} }
public void visit(Stat.NumericFor stat) { public void visit(Stat.NumericFor stat) {
visit(stat.name);
stat.initial.accept(this);
stat.step.accept(this);
stat.limit.accept(this);
stat.block.accept(this);
} }
public void visit(Stat.RepeatUntil stat) { public void visit(Stat.RepeatUntil stat) {
stat.block.accept(this);
stat.exp.accept(this);
} }
public void visit(Stat.Return stat) { public void visit(Stat.Return stat) {
visitExps(stat.values);
} }
public void visit(Stat.WhileDo stat) { public void visit(Stat.WhileDo stat) {
stat.exp.accept(this);
stat.block.accept(this);
} }
public void visit(FuncCall funcCall) { public void visit(FuncBody body) {
body.parlist.accept(this);
body.block.accept(this);
} }
public void visit(FuncBody funcBody) { public void visit(FuncArgs args) {
visitExps(args.exps);
} }
public void visit(FuncArgs funcArgs) { public void visit(TableField field) {
} if ( field.name != null );
public void visit(Field field) { visit( field.name );
} if ( field.index != null )
public void visit(Exp exp) { field.index.accept(this);
field.rhs.accept(this);
} }
public void visit(Exp.AnonFuncDef exp) { public void visit(Exp.AnonFuncDef exp) {
exp.funcbody.accept(this);
} }
public void visit(Exp.BinopExp exp) { public void visit(Exp.BinopExp exp) {
exp.lhs.accept(this);
exp.rhs.accept(this);
} }
public void visit(Exp.Constant exp) { public void visit(Exp.Constant exp) {
} }
public void visit(Exp.FieldExp exp) {
exp.lhs.accept(this);
visit(exp.name);
}
public void visit(Exp.FuncCall exp) {
exp.lhs.accept(this);
exp.args.accept(this);
}
public void visit(Exp.IndexExp exp) {
exp.lhs.accept(this);
exp.exp.accept(this);
}
public void visit(Exp.MethodCall exp) {
exp.lhs.accept(this);
visit(exp.name);
exp.args.accept(this);
}
public void visit(Exp.NameExp exp) {
visit(exp.name);
}
public void visit(Exp.ParensExp exp) {
exp.exp.accept(this);
}
public void visit(Exp.UnopExp exp) { public void visit(Exp.UnopExp exp) {
exp.rhs.accept(this);
} }
public void visit(Exp.VarargsExp exp) { public void visit(Exp.VarargsExp exp) {
} }
public void visit(PrimaryExp exp) { public void visit(ParList pars) {
visitNames(pars.names);
} }
public void visit(ParList parList) { public void visit(TableConstructor table) {
if( table.fields != null)
for ( TableField f: table.fields )
f.accept(this);
} }
public void visit(PostfixOp postfixOp) { public void visitVars(List<Exp.VarExp> vars) {
if ( vars != null )
for ( Exp.VarExp v: vars )
v.accept(this);
} }
public void visit(VarExp exp) { public void visitExps(List<Exp> exps) {
if ( exps != null )
for ( Exp e: exps )
e.accept(this);
}
public void visitNames(List<Name> names) {
if ( names != null )
for ( Name n: names )
visit(n);
}
private void visit(Name name) {
}
private void visit(String name) {
} }
} }