Created
March 20, 2015 13:08
-
-
Save rerorero/a101d66373a62878f0d6 to your computer and use it in GitHub Desktop.
LuaParser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package luuuaaa | |
import scala.util.parsing.input.Positional | |
sealed trait Node extends Positional | |
case class Name(name:String) extends Node | |
case class Number(value:Any) extends Node | |
case class StringVal(value:String) extends Node | |
case class Nil() extends Node | |
case class BoolVal(value:Boolean) extends Node | |
case class ThreeDot() extends Node | |
case class StatEnd() extends Node | |
case class Chunk(block:Block) extends Node | |
case class Block(stats:List[Stat], retStat:Option[RetStat]) extends Node | |
case class Stat(stat:Node) extends Node | |
case class Assign(varlist:VarList, expList:ExpList) extends Node | |
case class Break() extends Node | |
case class GoTo(name:Name) extends Node | |
case class DoBlock(block:Block) extends Node | |
case class WhileBlock(exp:Exp, block:Block) extends Node | |
case class RepeatBlock(block:Block, until:Exp) extends Node | |
case class IfBlock(lhs:Exp, rhs:Block, elIfs:List[ElIfBlock], elseBlock:Option[Block]) extends Node | |
case class ElIfBlock(lhs:Exp, rhs:Block) extends Node | |
case class ForName(lhs:Name, rhs:Exp, cond1 : Exp, cond2:Option[Exp], block:Block) extends Node | |
case class ForNameList(namelist:NameList, explist:ExpList, block:Block) extends Node | |
case class FunctionStat(funcName: FuncName, funcBody: FuncBody) extends Node | |
case class LocalFunctionStat(funcName: Name, funcBody: FuncBody) extends Node | |
case class LocalNameList(names:NameList, rhs:Option[ExpList]) extends Node | |
case class RetStat(exps:Option[ExpList]) extends Node | |
case class Label(name:Name) extends Node | |
case class FuncName(receiver:List[Name], message:Option[Name]) extends Node | |
case class VarList(vars:List[Var]) extends Node | |
case class Var(name:Option[Name], prefix : Option[PrefixExp], exp:Option[Exp]) extends Node | |
case class NameList(names:List[Name]) extends Node | |
case class ExpList(exps:List[Exp]) extends Node | |
case class Exp(exp:Node) extends Node | |
case class BinOpExp(lhs:Exp, op:BinOp, rhs:Exp) extends Node | |
case class UnOpExp(op:UnOp, rhs:Exp) extends Node | |
case class PrefixExp(prefix:Node) extends Node | |
case class FunctionCall(prefix:PrefixExp, name : Option[Name], args : Args) extends Node | |
case class Args(args:Node) extends Node | |
case class ExpListArgs(expList:Option[ExpList]) extends Node | |
case class FunctionDef(body:FuncBody) extends Node | |
case class FuncBody(parlist:Option[ParList], block:Block) extends Node | |
case class ParList(nameList:Option[NameList], args:Option[String]) extends Node | |
case class TableConstructor(fields:Option[FieldList]) extends Node | |
case class FieldList(field : Field, stepAndFields : List[FieldStepAndField], step : Option[FieldStep]) extends Node | |
case class FieldStepAndField(step:FieldStep, field:Field) extends Node | |
case class Field(lhs:Option[Node], rhs:Node) extends Node | |
case class FieldLhs(lhs:Node) extends Node | |
case class FieldStep(sep:String) extends Node | |
case class BinOp(op:String) extends Node | |
case class UnOp(op:String) extends Node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package luuuaaa | |
import scala.util.parsing.input.Positional | |
sealed trait Node extends Positional | |
case class Name(name:String) extends Node | |
case class Number(value:Any) extends Node | |
case class StringVal(value:String) extends Node | |
case class Nil() extends Node | |
case class BoolVal(value:Boolean) extends Node | |
case class ThreeDot() extends Node | |
case class StatEnd() extends Node | |
case class Chunk(block:Block) extends Node | |
case class Block(stats:List[Stat], retStat:Option[RetStat]) extends Node | |
case class Stat(stat:Node) extends Node | |
case class Assign(varlist:VarList, expList:ExpList) extends Node | |
case class Break() extends Node | |
case class GoTo(name:Name) extends Node | |
case class DoBlock(block:Block) extends Node | |
case class WhileBlock(exp:Exp, block:Block) extends Node | |
case class RepeatBlock(block:Block, until:Exp) extends Node | |
case class IfBlock(lhs:Exp, rhs:Block, elIfs:List[ElIfBlock], elseBlock:Option[Block]) extends Node | |
case class ElIfBlock(lhs:Exp, rhs:Block) extends Node | |
case class ForName(lhs:Name, rhs:Exp, cond1 : Exp, cond2:Option[Exp], block:Block) extends Node | |
case class ForNameList(namelist:NameList, explist:ExpList, block:Block) extends Node | |
case class FunctionStat(funcName: FuncName, funcBody: FuncBody) extends Node | |
case class LocalFunctionStat(funcName: Name, funcBody: FuncBody) extends Node | |
case class LocalNameList(names:NameList, rhs:Option[ExpList]) extends Node | |
case class RetStat(exps:Option[ExpList]) extends Node | |
case class Label(name:Name) extends Node | |
case class FuncName(receiver:List[Name], message:Option[Name]) extends Node | |
case class VarList(vars:List[Var]) extends Node | |
case class Var(name:Option[Name], prefix : Option[PrefixExp], exp:Option[Exp]) extends Node | |
case class NameList(names:List[Name]) extends Node | |
case class ExpList(exps:List[Exp]) extends Node | |
case class Exp(exp:Node) extends Node | |
case class BinOpExp(lhs:Exp, op:BinOp, rhs:Exp) extends Node | |
case class UnOpExp(op:UnOp, rhs:Exp) extends Node | |
case class PrefixExp(prefix:Node) extends Node | |
case class FunctionCall(prefix:PrefixExp, name : Option[Name], args : Args) extends Node | |
case class Args(args:Node) extends Node | |
case class ExpListArgs(expList:Option[ExpList]) extends Node | |
case class FunctionDef(body:FuncBody) extends Node | |
case class FuncBody(parlist:Option[ParList], block:Block) extends Node | |
case class ParList(nameList:Option[NameList], args:Option[String]) extends Node | |
case class TableConstructor(fields:Option[FieldList]) extends Node | |
case class FieldList(field : Field, stepAndFields : List[FieldStepAndField], step : Option[FieldStep]) extends Node | |
case class FieldStepAndField(step:FieldStep, field:Field) extends Node | |
case class Field(lhs:Option[Node], rhs:Node) extends Node | |
case class FieldLhs(lhs:Node) extends Node | |
case class FieldStep(sep:String) extends Node | |
case class BinOp(op:String) extends Node | |
case class UnOp(op:String) extends Node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package luuuaaa | |
import scala.util.parsing.combinator.PackratParsers | |
import scala.util.parsing.combinator.lexical.StdLexical | |
import scala.util.parsing.combinator.syntactical.StandardTokenParsers | |
object LuaParser extends StandardTokenParsers with PackratParsers { | |
def parse(input:String) = phrase(chunk)(new lexical.Scanner(input)) | |
override val lexical = new StdLexical | |
lexical.reserved ++= keywords | |
lexical.delimiters ++= delimiters | |
def delimiters =("+ - * / % ^ # == ~= <= >= < > = ( ) { } [ ] :: ; : , . .. ..." split ' ') | |
def keywords = ("and break do else elseif end false for function goto if in local nil not or repeat return then true until while" split ' ') | |
type P[T] = PackratParser[T] | |
def nil : P[Nil] = "nil" ^^^ Nil() | |
def boolval : P[BoolVal] = ("true" ^^^ BoolVal(true) | "false" ^^^ BoolVal(false)) | |
def number : P[Number] = numericLit ^^ (Number(_)) | |
def name : P[Name] = ident ^^ (Name(_)) | |
def stringVal : P[StringVal] = stringLit ^^ (StringVal(_)) | |
def threeDot : P[ThreeDot] = "..." ^^^ ThreeDot() | |
def statEnd : P[StatEnd] = ";" ^^^ StatEnd() | |
def chunk : P[Chunk] = block ^^ (Chunk(_)) | |
def block : P[Block] = rep(stat) ~ opt(retstat) ^^ {case stats ~ rets => Block(stats, rets)} | |
def stat : P[Stat]= (statEnd | assign | functioncall | label | breaks | goto | doblock | whileblock | repeatblock | ifblock | forname | localfunc | localnames | fornamelist) ^^ (Stat(_)) | |
def assign : P[Assign] = varList ~ "=" ~ explist ^^ {case vl ~ _ ~ el => Assign(vl, el)} | |
def breaks : P[Break] = "break" ^^^ Break() | |
def goto : P[GoTo] = "goto" ~> name ^^ (GoTo(_)) | |
def doblock : P[DoBlock] = "do" ~> block <~ "end" ^^ (DoBlock(_)) | |
def whileblock : P[WhileBlock] = "while" ~ exp ~ "do" ~ block ~ "end" ^^ { case _ ~ ex ~ _ ~ bl ~ _ => WhileBlock(ex, bl)} | |
def repeatblock : P[RepeatBlock] = "repeat" ~ block ~ "until" ~ exp ^^ { case _ ~ bl ~ _ ~ exp => RepeatBlock(bl, exp)} | |
def ifblock : P[IfBlock] = "if" ~ exp ~ "then" ~ block ~ rep(elifblock) ~ opt("else" ~> block) ^^ { | |
case _ ~ lhs ~ _ ~ rhs ~ elifs ~ els => IfBlock(lhs, rhs, elifs, els) | |
} | |
def elifblock : P[ElIfBlock] = "elseif" ~ exp ~ "then" ~ block ^^ { case _ ~ ex ~ _ ~ bl => ElIfBlock(ex, bl)} | |
def forname : P[ForName] = "for" ~ name ~ "=" ~ exp ~ "," ~ exp ~ opt("," ~> exp) ~ "do" ~ block ~ "end" ^^ { | |
case _ ~ lhs ~ _ ~ rhs ~ _ ~ cond1 ~ cond2 ~ _ ~ blk ~ _ => ForName(lhs, rhs, cond1, cond2, blk) | |
} | |
def fornamelist : P[ForNameList] = "for" ~ namelist ~ "in" ~ explist ~ "do" ~ block ~ "end" ^^ { | |
case _ ~ names ~ _ ~ exps ~ _ ~ block ~ _ => ForNameList(names, exps, block) | |
} | |
def localfunc : P[LocalFunctionStat] = "local" ~ "function" ~ name ~ funcbody ^^ {case _ ~ _ ~ n ~ body => LocalFunctionStat(n, body)} | |
def localnames : P[LocalNameList] = "local" ~ namelist ~ opt("=" ~> explist) ^^ { case _ ~ names ~ exps => LocalNameList(names, exps)} | |
def retstat : P[RetStat] = "return" ~ opt(explist) ~ opt(";") ^^ { case _ ~ exps ~ _ => RetStat(exps) } | |
def label : P[Label] = "::" ~> name <~ "::" ^^ (Label(_)) | |
def funcname : P[FuncName] = repsep(name, ",") ~ opt(":" ~> name) ^^ {case names ~ optName => FuncName(names, optName) } | |
def varList : P[VarList] = repsep(varVal, ",") ^^ (VarList(_)) | |
def varVal : P[Var] = (var1 | var2 | var3) | |
def var1 : P[Var] = name ^^ { case n => Var(Some(n), None, None) } | |
def var2 : P[Var] = prefixexp ~ "[" ~ exp ~ "]" ^^ {case pref ~ _ ~ exp ~ _ => Var(None, Some(pref), Some(exp))} | |
def var3 : P[Var] = prefixexp ~ "." ~ name ^^ { case pref ~ _ ~ name => Var(Some(name), Some(pref), None)} | |
def namelist : P[NameList] = repsep(name, ",") ^^ (NameList(_)) | |
def explist : P[ExpList] = repsep(exp, ",") ^^ (ExpList(_)) | |
def exp : P[Exp] = (nil | boolval | number | stringVal | threeDot | functiondef | prefixexp | tableContructor | binopexp | unopexp ) ^^ (Exp(_)) | |
def binopexp : P[BinOpExp] = exp ~ binop ~ exp ^^ {case e1 ~ op ~ e2 => BinOpExp(e1, op, e2)} | |
def unopexp : P[UnOpExp] = unop ~ exp ^^ {case op ~ e1 => UnOpExp(op, e1)} | |
def prefixexp : P[PrefixExp] = (varVal | functioncall | subExp) ^^ (PrefixExp(_)) | |
def subExp = "(" ~> exp <~ ")" | |
def functioncall: P[FunctionCall] = functioncall1 | functioncall2 | |
def functioncall1 = prefixexp ~ args ^^ { case exp ~ args => FunctionCall(exp, None, args) } | |
def functioncall2 = prefixexp ~ ":" ~ name ~ args ^^ { case exp ~ _ ~ name ~ args => FunctionCall(exp, Some(name), args) } | |
def args : P[Args] = (explistArgs | tableContructor | stringVal) ^^ (Args(_)) | |
def explistArgs : P[ExpListArgs] = "(" ~> opt(explist) <~ ")" ^^ (ExpListArgs(_)) | |
def functiondef : P[FunctionDef] = "function" ~> funcbody ^^ (FunctionDef(_)) | |
def funcbody : P[FuncBody] = "(" ~ opt(parlist) ~ ")" ~ block ~ "end" ^^ { case _ ~ pars ~ _ ~ block ~ _ => FuncBody(pars, block) } | |
// 微妙に違う | |
def parlist : P[ParList] = opt(namelist) ~ opt(",") ~ opt("...") ^^ { case names ~ cunma ~ args => ParList(names, args) } | |
def tableContructor : P[TableConstructor] = "{" ~> opt(fieldList) <~ "}" ^^ (TableConstructor(_)) | |
def fieldList : P[FieldList] = field ~ rep(fieldSepAndField) ~ opt(fieldsep) ^^ {case e1 ~ e2 ~ e3 => FieldList(e1, e2, e3)} | |
def fieldSepAndField = fieldsep ~ field ^^ {case e1 ~ e2 => FieldStepAndField(e1, e2) } | |
def field : P[Field] = opt(fieldLhs) ~ exp ^^ {case lhs ~ rhs => Field(lhs,rhs)} | |
def fieldLhs : P[FieldLhs] = (("[" ~> exp <~ "]") | name) <~ "=" ^^ (FieldLhs(_)) | |
def fieldsep : P[FieldStep] = ("," | ";") ^^ (FieldStep(_)) | |
def binop : P[BinOp] = ("+" | "-" | "*" | "/" | "^" | "%" | ".." | "<" | "<=" | ">" | ">=" | "==" | "~=" | "and" | "or") ^^ (BinOp(_)) | |
def unop : P[UnOp] = ("-" | "not" | "#") ^^ (UnOp(_)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment