Skip to content

Instantly share code, notes, and snippets.

@rerorero
Created March 20, 2015 13:08
Show Gist options
  • Save rerorero/a101d66373a62878f0d6 to your computer and use it in GitHub Desktop.
Save rerorero/a101d66373a62878f0d6 to your computer and use it in GitHub Desktop.
LuaParser
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
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
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