Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
|
|
@ -0,0 +1,209 @@
|
|||
package xyz.hyperreal.rosettacodeCompiler
|
||||
|
||||
import scala.io.Source
|
||||
|
||||
object SyntaxAnalyzer {
|
||||
|
||||
val symbols =
|
||||
Map[String, (PrefixOperator, InfixOperator)](
|
||||
"Op_or" -> (null, InfixOperator(10, LeftAssoc, BranchNode("Or", _, _))),
|
||||
"Op_and" -> (null, InfixOperator(20, LeftAssoc, BranchNode("And", _, _))),
|
||||
"Op_equal" -> (null, InfixOperator(30, LeftAssoc, BranchNode("Equal", _, _))),
|
||||
"Op_notequal" -> (null, InfixOperator(30, LeftAssoc, BranchNode("NotEqual", _, _))),
|
||||
"Op_less" -> (null, InfixOperator(40, LeftAssoc, BranchNode("Less", _, _))),
|
||||
"Op_lessequal" -> (null, InfixOperator(40, LeftAssoc, BranchNode("LessEqual", _, _))),
|
||||
"Op_greater" -> (null, InfixOperator(40, LeftAssoc, BranchNode("Greater", _, _))),
|
||||
"Op_greaterequal" -> (null, InfixOperator(40, LeftAssoc, BranchNode("GreaterEqual", _, _))),
|
||||
"Op_add" -> (PrefixOperator(30, identity), InfixOperator(50, LeftAssoc, BranchNode("Add", _, _))),
|
||||
"Op_minus" -> (PrefixOperator(70, BranchNode("Negate", _, TerminalNode)), InfixOperator(
|
||||
50,
|
||||
LeftAssoc,
|
||||
BranchNode("Subtract", _, _))),
|
||||
"Op_multiply" -> (null, InfixOperator(60, LeftAssoc, BranchNode("Multiply", _, _))),
|
||||
"Op_divide" -> (null, InfixOperator(60, LeftAssoc, BranchNode("Divide", _, _))),
|
||||
"Op_mod" -> (null, InfixOperator(60, RightAssoc, BranchNode("Mod", _, _))),
|
||||
"Op_not" -> (PrefixOperator(70, BranchNode("Not", _)), null),
|
||||
"LeftParen" -> null,
|
||||
"RightParen" -> null
|
||||
)
|
||||
|
||||
def apply = new SyntaxAnalyzer(symbols)
|
||||
|
||||
abstract class Node
|
||||
case class LeafNode(name: String, value: String) extends Node
|
||||
case class BranchNode(name: String, left: Node, right: Node = TerminalNode) extends Node
|
||||
case object TerminalNode extends Node
|
||||
|
||||
abstract class Assoc
|
||||
case object LeftAssoc extends Assoc
|
||||
case object RightAssoc extends Assoc
|
||||
|
||||
abstract class Operator
|
||||
case class InfixOperator(prec: Int, assoc: Assoc, compute: (Node, Node) => Node) extends Operator
|
||||
case class PrefixOperator(prec: Int, compute: Node => Node) extends Operator
|
||||
|
||||
}
|
||||
|
||||
class SyntaxAnalyzer(symbols: Map[String, (SyntaxAnalyzer.PrefixOperator, SyntaxAnalyzer.InfixOperator)]) {
|
||||
import SyntaxAnalyzer.{BranchNode, InfixOperator, LeafNode, LeftAssoc, Node, PrefixOperator, TerminalNode}
|
||||
|
||||
def fromStdin = fromSource(Source.stdin)
|
||||
|
||||
def fromString(src: String) = fromSource(Source.fromString(src))
|
||||
|
||||
def fromSource(s: Source) = {
|
||||
val tokens = ((s.getLines map (_.trim.split(" +", 4)) map {
|
||||
case Array(line, col, name) =>
|
||||
symbols get name match {
|
||||
case None | Some(null) => SimpleToken(line.toInt, col.toInt, name)
|
||||
case Some(operators) => OperatorToken(line.toInt, col.toInt, name, operators)
|
||||
}
|
||||
case Array(line, col, name, value) => ValueToken(line.toInt, col.toInt, name, value)
|
||||
}) toStream)
|
||||
|
||||
flatten(parse(tokens))
|
||||
}
|
||||
|
||||
def flatten(n: Node): Unit =
|
||||
n match {
|
||||
case TerminalNode => println(";")
|
||||
case LeafNode(name, value) => println(s"$name $value")
|
||||
case BranchNode(name, left, right) =>
|
||||
println(name)
|
||||
flatten(left)
|
||||
flatten(right)
|
||||
}
|
||||
|
||||
def parse(toks: Stream[Token]) = {
|
||||
var cur = toks
|
||||
|
||||
def next = cur = cur.tail
|
||||
|
||||
def token = cur.head
|
||||
|
||||
def consume = {
|
||||
val res = token
|
||||
|
||||
next
|
||||
res
|
||||
}
|
||||
|
||||
def accept(name: String) =
|
||||
if (token.name == name) {
|
||||
next
|
||||
true
|
||||
} else
|
||||
false
|
||||
|
||||
def expect(name: String, error: String = null) =
|
||||
if (token.name != name)
|
||||
sys.error(if (error eq null) s"expected $name, found ${token.name}" else s"$error: $token")
|
||||
else
|
||||
next
|
||||
|
||||
def expression(minPrec: Int): Node = {
|
||||
def infixOperator = token.asInstanceOf[OperatorToken].operators._2
|
||||
|
||||
def isInfix = token.isInstanceOf[OperatorToken] && infixOperator != null
|
||||
|
||||
var result =
|
||||
consume match {
|
||||
case SimpleToken(_, _, "LeftParen") =>
|
||||
val result = expression(0)
|
||||
|
||||
expect("RightParen", "expected closing parenthesis")
|
||||
result
|
||||
case ValueToken(_, _, name, value) => LeafNode(name, value)
|
||||
case OperatorToken(_, _, _, (prefix, _)) if prefix ne null => prefix.compute(expression(prefix.prec))
|
||||
case OperatorToken(_, _, _, (_, infix)) if infix ne null =>
|
||||
sys.error(s"expected a primitive expression, not an infix operator: $token")
|
||||
}
|
||||
|
||||
while (isInfix && infixOperator.prec >= minPrec) {
|
||||
val InfixOperator(prec, assoc, compute) = infixOperator
|
||||
val nextMinPrec = if (assoc == LeftAssoc) prec + 1 else prec
|
||||
|
||||
next
|
||||
result = compute(result, expression(nextMinPrec))
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
def parenExpression = {
|
||||
expect("LeftParen")
|
||||
|
||||
val e = expression(0)
|
||||
|
||||
expect("RightParen")
|
||||
e
|
||||
}
|
||||
|
||||
def statement: Node = {
|
||||
var stmt: Node = TerminalNode
|
||||
|
||||
if (accept("Keyword_if"))
|
||||
stmt = BranchNode("If",
|
||||
parenExpression,
|
||||
BranchNode("If", statement, if (accept("Keyword_else")) statement else TerminalNode))
|
||||
else if (accept("Keyword_putc")) {
|
||||
stmt = BranchNode("Prtc", parenExpression)
|
||||
expect("Semicolon")
|
||||
} else if (accept("Keyword_print")) {
|
||||
expect("LeftParen")
|
||||
|
||||
do {
|
||||
val e =
|
||||
if (token.name == "String")
|
||||
BranchNode("Prts", LeafNode("String", consume.asInstanceOf[ValueToken].value))
|
||||
else
|
||||
BranchNode("Prti", expression(0))
|
||||
|
||||
stmt = BranchNode("Sequence", stmt, e)
|
||||
} while (accept("Comma"))
|
||||
|
||||
expect("RightParen")
|
||||
expect("Semicolon")
|
||||
} else if (token.name == "Semicolon")
|
||||
next
|
||||
else if (token.name == "Identifier") {
|
||||
val ident = LeafNode("Identifier", consume.asInstanceOf[ValueToken].value)
|
||||
|
||||
expect("Op_assign")
|
||||
stmt = BranchNode("Assign", ident, expression(0))
|
||||
expect("Semicolon")
|
||||
} else if (accept("Keyword_while"))
|
||||
stmt = BranchNode("While", parenExpression, statement)
|
||||
else if (accept("LeftBrace")) {
|
||||
while (token.name != "RightBrace" && token.name != "End_of_input") {
|
||||
stmt = BranchNode("Sequence", stmt, statement)
|
||||
}
|
||||
|
||||
expect("RightBrace")
|
||||
} else
|
||||
sys.error(s"syntax error: $token")
|
||||
|
||||
stmt
|
||||
}
|
||||
|
||||
var tree: Node = TerminalNode
|
||||
|
||||
do {
|
||||
tree = BranchNode("Sequence", tree, statement)
|
||||
} while (token.name != "End_of_input")
|
||||
|
||||
expect("End_of_input")
|
||||
tree
|
||||
}
|
||||
|
||||
abstract class Token {
|
||||
val line: Int;
|
||||
val col: Int;
|
||||
val name: String
|
||||
}
|
||||
|
||||
case class SimpleToken(line: Int, col: Int, name: String) extends Token
|
||||
case class ValueToken(line: Int, col: Int, name: String, value: String) extends Token
|
||||
case class OperatorToken(line: Int, col: Int, name: String, operators: (PrefixOperator, InfixOperator)) extends Token
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue