Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import util.parsing.combinator.RegexParsers
- object FimppParser extends RegexParsers {
- var ERRORS:ErrorMessageProvider = Trollestia
- val keywords =
- Set("and","got","i","my","me","with","about","either","or","has","is","have","are","likes","did","only","like","when","had","was","were","in") //TODO
- val numbers = List("zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve")
- def fullStop: Parser[Unit] = "." ^^^ ()
- def headerEnd: Parser[Unit] = ("."|":") ^^^ ()
- def sentenceEnd: Parser[Unit] = ("."|"!") ^^^ ()
- def comma: Parser[Unit] = "," ^^^ ()
- def kw(strs: String*): Parser[Unit] = strs match{
- case Seq() => failure(ERRORS.unknownError)
- case Seq(str) =>
- if (str.endsWith("?") && str.length()>1) opt(kw(str.stripSuffix("?"))) ^^^ ()
- else if (str.endsWith("*") && str.length()>1) rep(kw(str.stripSuffix("*"))) ^^^ ()
- else if (str.endsWith("+") && str.length()>1) rep1(kw(str.stripSuffix("+"))) ^^^ ()
- else ("""\b"""+str+"""\b""").r ^^^ ()
- case _ => ("""\b"""+strs.head+"""\b""").r ~ kw(strs.tail:_*) ^^^ ()
- }
- def altkw(strs: String*):Parser[Unit] = strs match{
- case Seq() => failure(ERRORS.unknownError).asInstanceOf[Parser[Unit]]
- case Seq(str) => ("""\b"""+str+"""\b""").r ^^^ ()
- case _ => (("""\b"""+strs.head+"""\b""").r | altkw(strs.tail:_*)) ^^^ ()
- }
- def word: Parser[String] = ("""[A-Za-z]+('[a-z]+)?""".r) ^? ({
- case word if !keywords.contains(word) =>
- if(word=="friendship") "magic" else word
- },{ case notAWord =>
- ERRORS.invalidIdentifier(notAWord)
- })
- def identifier: Parser[String] = rep1(word) ^^ {l=>l.mkString(" ")} //TODO: the/a/an
- def listOfIdentifiers: Parser[List[String]] = (
- identifier~opt(comma)~and~identifier ^^ {case a~_~_~b => List(a,b)}
- | identifier~comma~listOfIdentifiers ^^ {case a~_~bs => a::bs}
- | identifier ^^ {x:String=>List(x)}
- )
- def and: Parser[Unit] = kw("and")
- def or: Parser[Unit] = kw("or")
- def number: Parser[Long] = (
- (opt(opt(kw("the"))~kw("number"))~>"""[0-9]+""".r) ^^ {s=>s.toLong}
- | word ^? {case word if numbers.contains(word) => numbers.indexOf(word).toLong}
- ) //TODO
- def stringLiteral: Parser[Expr] = "\"[^\"]*\"".r ^^ {sl =>
- StringInnardsParser.parseAll(StringInnardsParser.stringInnards,sl.stripPrefix("\"").stripSuffix("\"")).get
- }
- def literal: Parser[Expr] = (
- stringLiteral
- | number ^^ {v=>NumberValue(v)}
- )//TODO
- def listExpression: Parser[ListExpression] = (
- simpleExpression~opt(comma)~and~simpleExpression ^^ {case a~_~_~b => ListExpression(List(a,b))}
- | simpleExpression~comma~listExpression ^^ {case a~_~ListExpression(bs) => ListExpression(a::bs)}
- )
- def expression: Parser[Expr] =
- listExpression | kw("only")~>simpleExpression ^^ {e=>ListExpression(List(e))} | simpleExpression
- def simpleExpression: Parser[Expr] = literal | identifier ^^{id=>VariableValue(id)} //TODO
- def condition:Parser[Condition] = andCondition | orCondition | simpleCondition
- def simpleCondition:Parser[Condition] = relationalCondition //TODO
- def andCondition:Parser[Conjunction] = (
- simpleCondition~and~simpleCondition ^^ {case c1~_~c2 => Conjunction(List(c1,c2))}
- | simpleCondition~comma~andCondition ^^ {case c1~_~Conjunction(cs) => Conjunction(c1::cs)}
- )
- def orCondition = kw("either?")~>eitherLessOrCondition
- def eitherLessOrCondition:Parser[Alternative] = (
- simpleCondition~or~simpleCondition ^^ {case c1~_~c2 => Alternative(List(c1,c2))}
- | simpleCondition~comma~eitherLessOrCondition ^^ {case c1~_~Alternative(cs) => Alternative(c1::cs)}
- )
- def relationalCondition:Parser[Condition] = (
- expression~condOperator~expression ^^ {case e1~op~e2 => Relational(e1,op,e2)}
- | altkw("everything","everypony")~>kw("in")~>expression~condOperator~expression ^^ {case e1~op~e2 => Relational(e1,"all"+op,e2)}
- | altkw("anything","anypony")~>kw("in")~>expression~condOperator~expression ^^ {case e1~op~e2 => Relational(e1,"all"+op,e2)}
- )
- def hasOrHave:Parser[Unit] = altkw("has","have","had")
- def isOrAre:Parser[Unit] = altkw("is","are","was","were")
- def condOperator:Parser[String] = (
- hasOrHave~kw("less","than") ^^^ "<"
- | hasOrHave~kw("more","than") ^^^ ">"
- ) //TODO
- def function: Parser[Function] = (
- opt(kw("today"))~(kw("i","learned","about?")~>identifier~opt(kw("with")~>listOfIdentifiers)<~headerEnd)
- ~rep(statement) ~
- (kw("that's","about")~>identifier~opt(kw("with")~>listOfIdentifiers)<~sentenceEnd)) ^? ({
- case today~(fName~args)~stats~(fName2~args2) if fName==fName2 =>
- Function(today.isDefined, fName, args.getOrElse(Nil),stats)
- }, {
- case today~(fName~args)~stats~(fName2~args2) =>
- ERRORS.mismatchedFunctionNameInFooter(fName,fName2)
- case _ =>
- ERRORS.unknownError
- })
- def increment: Parser[Increment] = (
- identifier~(kw("got"))~number~(kw("less")^^^(-1) | kw("fewer")^^^ (-1) | kw("more")^^^1)<~sentenceEnd
- ^^ {
- case i~_~n~dir =>
- Increment(i,n*dir)
- }
- )
- def assignment: Parser[Assignment] = (
- kw("did","you","know","that?")
- ~> identifier
- ~ altkw("likes","is","like","are")
- ~expression<~ "?"
- ^^ {
- case i~_~e=> Assignment(i,e);
- })
- def ifStat: Parser[IfStat] = (
- (kw("when") ~> condition <~ headerEnd)
- ~ rep(statement)
- ~ opt(kw("in","the","end")~comma~kw("i","did","this","instead")~headerEnd~>rep(statement))
- <~ kw("that's","what","i","did")<~sentenceEnd
- ^^ {
- case cond~body1~body2 =>
- IfStat(cond,body1,body2.getOrElse(Nil))
- }
- )
- def whileStat: Parser[WhileStat] = (
- (kw("i","did","this","while") ~> condition <~ headerEnd)
- ~ rep(statement)
- ~ opt(kw("in","the","end")~comma~kw("i","did","this","instead")~headerEnd~>rep(statement))
- <~ kw("that's","what","i","did")<~sentenceEnd
- ^^ {
- case cond~body1~body2 =>
- WhileStat(cond,body1,body2.getOrElse(Nil))
- }
- )
- def printStat: Parser[PrintStat] = kw("i")~>altkw("sang","wrote","said")~>opt(kw("that")|comma|":")~>expression<~sentenceEnd ^^ {e=>PrintStat(e)}
- def statement: Parser[Statement] = assignment | ifStat | whileStat | printStat | increment
- def module:Parser[Module] = (
- (kw("dear","princess","celestia") ~> ":" ~> identifier <~ headerEnd)
- ~ rep(function)
- <~ (kw("your","faithful","student")~comma~identifier~opt(sentenceEnd))
- ^^ {
- case name~functions => Module(name,functions)
- }
- )
- def parseFim(s:String):Option[Module] = {
- parseAll(module,s) match {
- case Success(fimModule,_) => Some(fimModule)
- case Failure(errorMsg,_) =>
- println(errorMsg)
- None
- }
- }
- }
- object StringInnardsParser extends RegexParsers {
- override val whiteSpace = "".r
- def expression: Parser[Expr] = """[^"']+""".r ^^ {e=> FimppParser.parseAll(FimppParser.expression,e).get}
- def stringInnards: Parser[Concatenation] = rep(
- ("""[^"']+""".r ^^ {s=>StringValue(s)})
- | ("\'"~>expression<~"\'")
- )^^(l=>Concatenation(l))
- }
- case class Function(main:Boolean, name:String, argNames:List[String], body:List[Statement])
- sealed trait Expr
- case class NumberValue(value: Long) extends Expr
- case class StringValue(value: String) extends Expr
- case class Concatenation(exprs: List[Expr]) extends Expr
- case class ListExpression(elems: List[Expr]) extends Expr
- case class VariableValue(ident: String) extends Expr
- sealed trait Condition
- case class Conjunction(conds: List[Condition])extends Condition
- case class Alternative(conds: List[Condition])extends Condition
- case class Relational(left: Expr, op: String, right: Expr)extends Condition
- case class TrivialCondition(value: Boolean) extends Condition
- sealed trait Statement
- case class Assignment(variable: String, value: Expr) extends Statement
- case class Increment(variable: String, value: Long) extends Statement
- case class IfStat(cond: Condition, body: List[Statement], body2: List[Statement]) extends Statement
- case class WhileStat(cond: Condition, body:List[Statement], body2:List[Statement]) extends Statement
- case class PrintStat(expr: Expr) extends Statement
- case class Module(name:String, functions:List[Function])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement