/******************************************************************************* * 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. ******************************************************************************/ /** * Javacc grammar used to produce a parse tree. * */ options { STATIC = false; JDK_VERSION = "1.3"; ERROR_REPORTING = false; DEBUG_LOOKAHEAD = false; DEBUG_PARSER = false; DEBUG_TOKEN_MANAGER = false; OUTPUT_DIRECTORY = "src/jse/org/luaj/vm2/parser"; } PARSER_BEGIN(LuaParser) package org.luaj.vm2.parser; import org.luaj.vm2.*; import org.luaj.vm2.ast.*; import java.util.*; public class LuaParser { public static void main(String args[]) throws ParseException { LuaParser parser = new LuaParser(System.in); parser.Chunk(); } private static VarExp assertvarexp(PrimaryExp pe) throws ParseException { if (!pe.isvarexp()) throw new ParseException("exptected variable"); return (VarExp) pe; } private static FuncCall assertfunccall(PrimaryExp pe) throws ParseException { if (!pe.isfunccall()) throw new ParseException("expected function call"); return (FuncCall) pe; } } PARSER_END(LuaParser) /* WHITE SPACE */ SKIP : { " " | "\t" | "\n" | "\r" | "\f" } /* COMMENTS and LONG STRINGS */ MORE : { "--[[": IN_LC0 | "--[=[": IN_LC1 | "--[==[": IN_LC2 | "--[===[": IN_LC3 | < "--[====" ("=")* "[" > : IN_LCN | "[[" : IN_LS0 | "[=[" : IN_LS1 | "[==[" : IN_LS2 | "[===[" : IN_LS3 | < "[====" ("=")* "[" > : IN_LSN | "--" : IN_COMMENT } SPECIAL_TOKEN : { : DEFAULT } SPECIAL_TOKEN : { : DEFAULT } SPECIAL_TOKEN : { : DEFAULT } SPECIAL_TOKEN : { : DEFAULT } SPECIAL_TOKEN : { : DEFAULT } SPECIAL_TOKEN : { : DEFAULT } TOKEN : { : DEFAULT } TOKEN : { : DEFAULT } TOKEN : { : DEFAULT } TOKEN : { : DEFAULT } TOKEN : { : DEFAULT } MORE : { < ~[] > } /* RESERVED WORDS AND LITERALS */ TOKEN : { | | | | | | | | | | | | | | | | | | | | } /* LITERALS */ TOKEN : { < NAME: ["a"-"z", "A"-"Z", "_"] (["a"-"z", "A"-"Z", "_", "0"-"9"])* > | < NUMBER: | > | < #FLOAT: ()+ "." ()* ()? | "." ()+ ()? | ()+ ()? > | < #DIGIT: ["0"-"9"] > | < #EXP: ["e","E"] (["+","-"])? ()+ > | < #HEX: "0" ["x","X"] ()+ > | < #HEXDIGIT: ["0"-"9","a"-"f","A"-"F"] > | < STRING: "\"" ( | ~["\\","\""])* "\"" > | < CHARSTRING: "'" ( | ~["\\","'"])* "'" > | < #QUOTED: | | > | < #DECIMAL: "\\" ["0"-"9"] (["0"-"9"])? (["0"-"9"])? > | < #UNICODE: "\\" "u" > //| < #CHAR: "\\" ("a"|"b"|"f"|"n"|"r"|"t"|"v"|"["|"]"|"'"|"\""|"\\"|"0"|) > | < #CHAR: "\\" (~[]) > | < #LF: ("\n" | "\r" | "\r\n") > } /** Root production. */ Chunk Chunk(): { Block b; } { b=Block() { return new Chunk(b); } } Block Block(): { Block b = new Block(); Stat s; } { (s=Stat() (";")? {b.add(s);} )* (s=LastStat() (";")? {b.add(s);} )? { return b; } } Stat Stat(): { Block b,b2; Exp e,e2,e3=null; Stat s; FuncName fn; FuncBody fb; Token n; List nl; List el=null; } { b=Block() { return Stat.block(b); } | e=Exp() b=Block() { return Stat.whiledo(e,b); } | b=Block() e=Exp() { return Stat.repeatuntil(b,e); } | s=IfThenElse() { return s; } | LOOKAHEAD(3) n= "=" e=Exp() "," e2=Exp() ( "," e3=Exp() )? b=Block() { return Stat.fornumeric(n.image,e,e2,e3,b); } | nl=NameList() el=ExpList() b=Block() { return Stat.forgeneric(nl,el,b); } | fn=FuncName() fb=FuncBody() { return Stat.functiondef(fn,fb); } | LOOKAHEAD(2) n= fb=FuncBody() { return Stat.localfunctiondef(n.image,fb); } | nl=NameList() ( "=" el=ExpList() )? { return Stat.localassignment(nl,el); } | s=ExprStat() { return s; } } Stat IfThenElse(): { Block b,b2,b3=null; Exp e,e2; List el=null; List bl=null; } { e=Exp() b=Block() ( e2=Exp() b2=Block() { if (el==null) el=new ArrayList(); if (bl==null) bl=new ArrayList(); el.add(e2); bl.add(b2); } )* ( b3=Block())? { return Stat.ifthenelse(e,b,el,bl,b3); } } Stat LastStat(): { List el=null; } { { return Stat.breakstat(); } | ( el=ExpList() )? { return Stat.returnstat(el); } } Stat ExprStat(): { PrimaryExp pe; Stat as=null; } { pe=PrimaryExp() ( as=Assign(assertvarexp(pe)) )? { return as==null? Stat.functioncall(assertfunccall(pe)): as; } } Stat Assign(VarExp v0): { List vl = new ArrayList(); vl.add(v0); VarExp ve; List el; } { ( "," ve=VarExp() { vl.add(ve); } )* "=" el=ExpList() { return Stat.assignment(vl,el); } } VarExp VarExp(): { PrimaryExp pe; } { pe=PrimaryExp() { return assertvarexp(pe); } } FuncName FuncName(): { FuncName fn; Token n; } { n= {fn=new FuncName(n.image);} ( "." n= {fn.adddot(n.image);} )* ( ":" n= {fn.method=n.image;} )? {return fn;} } PrimaryExp PrefixExp(): { Token n; Exp e; } { n= { return PrimaryExp.nameprefix(n.image); } | "(" e=Exp() ")" { return PrimaryExp.parensprefix(e); } } PrimaryExp PrimaryExp(): { PrimaryExp pe; PostfixOp po; } { pe=PrefixExp() ( LOOKAHEAD(2) po=PostfixOp() {pe=pe.append(po);} )* { return pe; } } PostfixOp PostfixOp(): { Token n; Exp e; FuncArgs a; } { "." n= { return PostfixOp.fieldop(n.image); } | "[" e=Exp() "]" { return PostfixOp.indexop(e); } | ":" n= a=FuncArgs() { return PostfixOp.methodop(n.image,a); } | a=FuncArgs() { return PostfixOp.functionop(a); } } FuncArgs FuncArgs(): { List el=null; TableConstructor tc; LuaString s; } { "(" ( el=ExpList() )? ")" { return FuncArgs.explist(el); } | tc=TableConstructor() { return FuncArgs.tableconstructor(tc); } | s=Str() { return FuncArgs.string(s); } } List NameList(): { List nl = new ArrayList(); Token name; } { name= {nl.add(new Name(name.image));} ( LOOKAHEAD(2) "," name= {nl.add(new Name(name.image));} )* {return nl;} } List ExpList(): { List el = new ArrayList(); Exp e; } { e=Exp() {el.add(e);} ( "," e=Exp() {el.add(e);} )* {return el;} } Exp SimpleExp(): { Token n; LuaString s; Exp e; TableConstructor tc; FuncBody fb; } { { return Exp.constant(LuaValue.NIL); } | { return Exp.constant(LuaValue.TRUE); } | { return Exp.constant(LuaValue.FALSE); } | n= { return Exp.constant(LuaValue.valueOf(Double.valueOf(n.image))); } | s=Str() { return Exp.constant(s); } | "..." { return Exp.varargs(); } | tc=TableConstructor() { return Exp.tableconstructor(tc); } | fb=Function() { return Exp.anonymousfunction(fb); } | e=PrimaryExp() { return e; } } LuaString Str(): {} { { return Str.quoteString(token.image); } | { return Str.charString(token.image); } | { return Str.longString(token.image); } | { return Str.longString(token.image); } | { return Str.longString(token.image); } | { return Str.longString(token.image); } | { return Str.longString(token.image); } } Exp Exp(): { Exp e,s; int op; } { ( e=SimpleExp() | op=Unop() s=Exp() {e=Exp.unaryexp(op,s);}) (LOOKAHEAD(2) op=Binop() s=Exp() {e=Exp.binaryexp(e,op,s);} )* { return e; } } FuncBody Function(): { FuncBody fb; } { fb=FuncBody() { return fb; } } FuncBody FuncBody(): { ParList pl=null; Block b; } { "(" ( pl=ParList() )? ")" b=Block() { return new FuncBody(pl,b); } } ParList ParList(): { List nl=null; boolean v=false; } { nl=NameList() ( "," "..." { v=true; } )? { return new ParList(nl,v); } | "..." { return new ParList(null,true); ; } } TableConstructor TableConstructor(): { TableConstructor tc = new TableConstructor(); List fl = null; } { "{" ( fl=FieldList() {tc.fields=fl;} )? "}" { return tc; } } List FieldList(): { List fl = new ArrayList(); Field f; } { f=Field() {fl.add(f);} (LOOKAHEAD(2) FieldSep() f=Field() {fl.add(f);})* (FieldSep())? { return fl; } } Field Field(): { Token name; Exp exp,rhs; } { "[" exp=Exp() "]" "=" rhs=Exp() { return Field.keyedField(exp,rhs); } | LOOKAHEAD(2) name= "=" rhs=Exp() { return Field.namedField(name.image,rhs); } | rhs=Exp() { return Field.listField(rhs); } } void FieldSep(): {} { "," | ";" } int Binop(): {} { "+" { return Lua.OP_ADD; } | "-" { return Lua.OP_SUB; } | "*" { return Lua.OP_MUL; } | "/" { return Lua.OP_DIV; } | "^" { return Lua.OP_POW; } | "%" { return Lua.OP_MOD; } | ".." { return Lua.OP_CONCAT; } | "<" { return Lua.OP_LT; } | "<=" { return Lua.OP_LE; } | ">" { return Lua.OP_GT; } | ">=" { return Lua.OP_GE; } | "==" { return Lua.OP_EQ; } | "~=" { return Lua.OP_NEQ; } | { return Lua.OP_AND; } | { return Lua.OP_OR; } } int Unop(): {} { "-" { return Lua.OP_UNM; } | { return Lua.OP_NOT; } | "#" { return Lua.OP_LEN; } }