Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
make single assignment a BinOp with "=" as the operator;
multiple assignment still to do.
  • Loading branch information
prakashk committed May 22, 2013
1 parent 7eba5f3 commit 5f73947
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 42 deletions.
5 changes: 5 additions & 0 deletions src/main/scala/org/moe/ast/AST.scala
Expand Up @@ -85,6 +85,11 @@ case class SubroutineDeclarationNode(name: String, signature: SignatureNode, bod
case class AttributeDeclarationNode(name: String, expression: AST) extends AST
case class VariableDeclarationNode(name: String, expression: AST) extends AST

case class AttributeNameNode(name: String) extends AST
case class VariableNameNode(name: String) extends AST
case class ArrayElementNameNode(arrayName: String, indices: List[AST]) extends AST
case class HashElementNameNode(hashName: String, indices: List[AST]) extends AST

case class ClassAccessNode(name: String) extends AST
case class AttributeAccessNode(name: String) extends AST
case class VariableAccessNode(name: String) extends AST
Expand Down
28 changes: 28 additions & 0 deletions src/main/scala/org/moe/ast/Serializer.scala
Expand Up @@ -196,6 +196,7 @@ object Serializer {
)
)

case AttributeNameNode(name) => JSONObject(Map("AttributeNameNode" -> name))
case AttributeAccessNode(name) => JSONObject(Map("AttributeAccessNode" -> name))
case AttributeAssignmentNode(name, expression) => JSONObject(
Map(
Expand Down Expand Up @@ -228,6 +229,7 @@ object Serializer {
)
)

case VariableNameNode(name) => JSONObject(Map("VariableNameNode" -> name))
case VariableAccessNode(name) => JSONObject(Map("VariableAccessNode" -> name))
case VariableAssignmentNode(name, expression) => JSONObject(
Map(
Expand Down Expand Up @@ -261,6 +263,19 @@ object Serializer {
)
)

case HashElementNameNode(hashName, keys) => JSONObject(
Map(
"HashElementNameNode" -> JSONObject(
Map(
"hashname" -> hashName,
if (keys.length == 1)
"key" -> toJSON(keys.head)
else
"keys" -> JSONArray(keys.map(toJSON(_)))
)
)
)
)
case HashElementAccessNode(hashName, keys) => JSONObject(
Map(
"HashElementAccessNode" -> JSONObject(
Expand Down Expand Up @@ -289,6 +304,19 @@ object Serializer {
)
)

case ArrayElementNameNode(arrayName, indices) => JSONObject(
Map(
"ArrayElementNameNode" -> JSONObject(
Map(
"arrayname" -> arrayName,
if (indices.length == 1)
"index" -> toJSON(indices.head)
else
"indices" -> JSONArray(indices.map(toJSON(_)))
)
)
)
)
case ArrayElementAccessNode(arrayName, indices) => JSONObject(
Map(
"ArrayElementAccessNode" -> JSONObject(
Expand Down
15 changes: 13 additions & 2 deletions src/main/scala/org/moe/interpreter/guts/Operators.scala
Expand Up @@ -20,7 +20,18 @@ object Operators extends Utils {
callMethod(receiver, "postfix:<" + operator + ">", List())
}

// binary operators
// assignment

case (env, BinaryOpNode(lhs: AST, "=", rhs: AST)) => {
lhs match {
case VariableNameNode(var_) => i.evaluate(env, VariableAssignmentNode(var_, rhs))
case AttributeNameNode(attr) => i.evaluate(env, AttributeAssignmentNode(attr, rhs))
case ArrayElementNameNode(array, index) => i.evaluate(env, ArrayElementLvalueNode(array, index, rhs))
case HashElementNameNode(hash, key) => i.evaluate(env, HashElementLvalueNode(hash, key, rhs))
}
}

// other binary operators

case (env, BinaryOpNode(lhs: AST, operator: String, rhs: AST)) => {
val receiver = i.evaluate(env, lhs)
Expand All @@ -46,4 +57,4 @@ object Operators extends Utils {
callMethod(receiver, "infix:<?:>", List(argTrue, argFalse))
}
}
}
}
98 changes: 58 additions & 40 deletions src/main/scala/org/moe/parser/MoeProductions.scala
Expand Up @@ -13,7 +13,7 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse
*********************************************************************
*/

lazy val expression: PackratParser[AST] = ternaryOp
lazy val expression: PackratParser[AST] = assignOp

// TODO: left or xor
// TODO: left and
Expand All @@ -22,6 +22,11 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse
// TODO: left , =>
// TODO: right = += -= *= etc.

// right = (assignment)
lazy val assignOp: PackratParser[AST] = lvalue ~ "=" ~ assignOp ^^ {
case left ~ "=" ~ right => BinaryOpNode(left, "=", right)
} | ternaryOp

// right ?:
lazy val ternaryOp: PackratParser[AST] = logicalOrOp ~ "?" ~ ternaryOp ~ ":" ~ ternaryOp ^^ {
case cond ~ "?" ~ trueExpr ~ ":" ~ falseExpr => TernaryOpNode(cond, trueExpr, falseExpr)
Expand Down Expand Up @@ -72,6 +77,11 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse
// left * / % x
lazy val mulOp: PackratParser[AST] = mulOp ~ "[*/%x]".r ~ expOp ^^ {
case left ~ op ~ right => BinaryOpNode(left, op, right)
} | matchOp

// left =~ TODO: !~
lazy val matchOp: PackratParser[AST] = matchOp ~ "=~" ~ expOp ^^ {
case left ~ op ~ right => BinaryOpNode(left, op, right)
} | expOp

// TODO: left =~ !~
Expand Down Expand Up @@ -208,14 +218,20 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse

// access

def variableName = """[$@%&][a-zA-Z_][a-zA-Z0-9_]*""".r
def variable = variableName ^^ VariableAccessNode
def variableName = """[$@%&][a-zA-Z_][a-zA-Z0-9_]*""".r ^^ { v => VariableNameNode(v) }
def variable = variableName ^^ {
case VariableNameNode(v) => VariableAccessNode(v)
}

def specialVariableName = """[$@%&][?*][A-Z_]+""".r | "$!"
def specialVariable = specialVariableName ^^ VariableAccessNode
def specialVariableName = ("""[$@%&][?*][A-Z_]+""".r | "$!") ^^ { v => VariableNameNode(v) }
def specialVariable = specialVariableName ^^ {
case VariableNameNode(v) => VariableAccessNode(v)
}

def attributeName = """[$@%&]![a-zA-Z_][a-zA-Z0-9_]*""".r
def attribute = attributeName ^^ AttributeAccessNode
def attributeName = """[$@%&]![a-zA-Z_][a-zA-Z0-9_]*""".r ^^ { a => AttributeNameNode(a) }
def attribute = attributeName ^^ {
case AttributeNameNode(a) => AttributeAccessNode(a)
}

def parameterName = """([$@%&])([a-zA-Z_][a-zA-Z0-9_]*)""".r

Expand All @@ -226,21 +242,33 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse
def arrayVariableName = """@[a-zA-Z_][a-zA-Z0-9_]*""".r
def hashVariableName = """%[a-zA-Z_][a-zA-Z0-9_]*""".r

private lazy val array_index_rule = arrayVariableName ~ ( "[" ~> expression <~ "]" ).+
private lazy val hash_index_rule = hashVariableName ~ ( "{" ~> expression <~ "}" ).+
def array_index_rule = arrayVariableName ~ ( "[" ~> expression <~ "]" ).+ ^^ {
case a ~ i => ArrayElementNameNode(a, i)
}
def hash_index_rule = hashVariableName ~ ( "{" ~> expression <~ "}" ).+ ^^ {
case h ~ k => HashElementNameNode(h, k)
}

def arrayIndex = array_index_rule ^^ {
case i ~ exprs => ArrayElementAccessNode(i, exprs)
case ArrayElementNameNode(i, exprs) => ArrayElementAccessNode(i, exprs)
}

def hashIndex = hash_index_rule ^^ {
case i ~ exprs => HashElementAccessNode(i, exprs)
case HashElementNameNode(h, exprs) => HashElementAccessNode(h, exprs)
}

def lvalue: Parser[AST] = (
array_index_rule
| hash_index_rule
| attributeName
| variableName
| specialVariableName
)

// assignment

def variableDeclaration = "my" ~> variableName ~ ("=" ~> expression).? ^^ {
case v ~ expr => VariableDeclarationNode(v, expr.getOrElse(UndefLiteralNode()))
case VariableNameNode(v) ~ expr => VariableDeclarationNode(v, expr.getOrElse(UndefLiteralNode()))
}

private def zipEm (x: List[String], y: List[AST], f: ((String, AST)) => AST): List[AST] = {
Expand All @@ -253,34 +281,27 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse
}

def multiVariableDeclaration = "my" ~> ("(" ~> repsep(variableName, ",") <~ ")") ~ ("=" ~> "(" ~> repsep(expression, ",") <~ ")").? ^^ {
case vars ~ None => StatementsNode(vars.map(VariableDeclarationNode(_, UndefLiteralNode())))
case vars ~ Some(exprs) => StatementsNode(zipEm(vars, exprs, (p) => VariableDeclarationNode(p._1, p._2)))
case vars ~ None => StatementsNode(
vars.map( { case VariableNameNode(v) => VariableDeclarationNode(v, UndefLiteralNode()) } )
)
case vars ~ Some(exprs) => StatementsNode(
zipEm(vars.map( { case VariableNameNode(v) => v } ),
exprs,
(p) => VariableDeclarationNode(p._1, p._2))
)
}

def variableAssignment = variableName ~ "=" ~ expression ^^ {
case v ~ _ ~ expr => VariableAssignmentNode(v, expr)
}

def multiVariableAssignment = ("(" ~> repsep(variableName, ",") <~ ")") ~ "=" ~ ("(" ~> repsep(expression, ",") <~ ")") ^^ {
case vars ~ _ ~ exprs => MultiVariableAssignmentNode(vars, exprs)
case vars ~ _ ~ exprs => MultiVariableAssignmentNode(
vars.map( { case VariableNameNode(vname) => vname } ),
exprs
)
}

def attributeAssignment = attributeName ~ "=" ~ expression ^^ {
case v ~ _ ~ expr => AttributeAssignmentNode(v, expr)
}

def multiAttributeAssignment = ("(" ~> repsep(attributeName, ",") <~ ")") ~ "=" ~ ("(" ~> repsep(expression, ",") <~ ")") ^^ {
case vars ~ _ ~ exprs => MultiAttributeAssignmentNode(vars, exprs)
case vars ~ _ ~ exprs => MultiAttributeAssignmentNode(vars.map({case AttributeNameNode(aname) => aname}), exprs)
}

def arrayElementAssignment = array_index_rule ~ "=" ~ expression ^^ {
case array ~ index_exprs ~ "=" ~ value_expr => ArrayElementLvalueNode(array, index_exprs, value_expr)
}

def hashElementAssignment = hash_index_rule ~ "=" ~ expression ^^ {
case hash ~ key_exprs ~ "=" ~ value_expr => HashElementLvalueNode(hash, key_exprs, value_expr)
}

/**
*********************************************************************
* Now we are getting into statements,
Expand Down Expand Up @@ -353,7 +374,7 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse
// Classes

def attributeDecl = "has" ~> attributeName ~ ("=" ~> expression).? ^^ {
case v ~ expr => AttributeDeclarationNode(v, expr.getOrElse(UndefLiteralNode()))
case AttributeNameNode(v) ~ expr => AttributeDeclarationNode(v, expr.getOrElse(UndefLiteralNode()))
}

def methodDecl: Parser[MethodDeclarationNode] = ("method" ~> identifier ~ ("(" ~> repsep(parameter, ",") <~ ")").?) ~ block ^^ {
Expand Down Expand Up @@ -420,8 +441,9 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse
}

def topicVariable = ("my".? ~> variableName) ^^ {
v => VariableDeclarationNode(v, UndefLiteralNode())
case VariableNameNode(v) => VariableDeclarationNode(v, UndefLiteralNode())
}

def foreachBlock = "for(each)?".r ~> opt(topicVariable) ~ ("(" ~> expression <~ ")") ~ block ^^ {
case Some(topic) ~ list ~ block => ForeachNode(topic, list, block)
case None ~ list ~ block => ForeachNode(VariableDeclarationNode("$_", UndefLiteralNode()), list, block)
Expand All @@ -436,7 +458,7 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse
}

def catchBlock: Parser[CatchNode] = ("catch" ~ "(") ~> namespacedIdentifier ~ variableName ~ (")" ~> block) ^^ {
case a ~ b ~ c => CatchNode(a, b, c)
case a ~ VariableNameNode(b) ~ c => CatchNode(a, b, c)
}

def finallyBlock: Parser[FinallyNode] = "finally" ~> block ^^ FinallyNode
Expand Down Expand Up @@ -468,14 +490,10 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse
lazy val simpleStatement: Parser[AST] = (
variableDeclaration
| multiVariableDeclaration
| variableAssignment
| expression
| multiVariableAssignment
| attributeAssignment
| multiAttributeAssignment
| useStatement
| arrayElementAssignment
| hashElementAssignment
| expression
)

/**
Expand Down

0 comments on commit 5f73947

Please sign in to comment.