Skip to content

Commit

Permalink
Rewrote the parser so it wouldn't choke on parenthesized lambdas.
Browse files Browse the repository at this point in the history
Also, added two new tasty operators, << and >>
(They do what you expect them to do)
  • Loading branch information
bluebear94 committed Jan 24, 2014
1 parent 3024ba4 commit c7b6e7f
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/main/scala/cmdreader/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ object Global {
val TWO = new BigInteger("2")
val vM = 0
val vm = 5
val vr = 6
val vr = 7
val version = vM + "." + vm + "." + vr
val r: Random = new Random
}
1 change: 1 addition & 0 deletions src/main/scala/cmdreader/PStandard.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ object PStandard {
val CONJUNCTION = 100
val DISJUNCTION = 50
val DOUBLE_OP = 1600
val SHIFT = 175
}
2 changes: 2 additions & 0 deletions src/main/scala/cmdreader/std/Loader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,7 @@ class Loader {
Global.liblist("std").loadCmd("Abs")
Global.liblist("std").loadCmd("Floor")
Global.liblist("std").loadCmd("FPart")
Global.liblist("std").loadCmd("OShl")
Global.liblist("std").loadCmd("OShr")
}
}
19 changes: 19 additions & 0 deletions src/main/scala/cmdreader/std/OShl.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cmdreader.std

import cmdreader._
import types._
import util._
import java.math.BigInteger

class OShl extends CommandOperator {
override def getName(): String = "shl"
override def getOpAlias() = "<<"
override def isValidArg0(n: Int) = n == 2
override def apply(args: Array[Type]): Type = {
MathUtil.shl(args(0), args(1))
}
def getPrecedence() = PStandard.SHIFT
def isReversed() = false
def hasAssignmentEquiv() = true
def getDoubleBase() = None
}
19 changes: 19 additions & 0 deletions src/main/scala/cmdreader/std/OShr.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cmdreader.std

import cmdreader._
import types._
import util._
import java.math.BigInteger

class OShr extends CommandOperator {
override def getName(): String = "shr"
override def getOpAlias() = ">>"
override def isValidArg0(n: Int) = n == 2
override def apply(args: Array[Type]): Type = {
MathUtil.shr(args(0), args(1))
}
def getPrecedence() = PStandard.SHIFT
def isReversed() = false
def hasAssignmentEquiv() = true
def getDoubleBase() = None
}
4 changes: 2 additions & 2 deletions src/main/scala/parse/ast/Expression.scala
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ class XprInt extends JavaTokenParsers with PackratParsers {
}
def expression: PackratParser[Expression] = control | ternary | assign | getOpEq | operator(ops.firstKey) | delete | sbexpression
def sbwrapper: PackratParser[SBExpression] = "(" ~> expression <~ ")" ^^ { x => SBWrapper(x) }
def sbexpression: PackratParser[SBExpression] = getUnary | sbwrapper | compound | literal | (getLOpOp ||| getOpOpL) | variable | ans | answer
def sbexpression: PackratParser[SBExpression] = getUnary | compound | literal | (getLOpOp ||| getOpOpL) | variable | answer | ans | sbwrapper
def getOpEq: PackratParser[Expression] = {
if (oeOps.isEmpty) failure("no such operator")
else lvalue ~ (oeOps.tail.foldLeft(literal(oeOps.head))((p, op) => p | op)) ~ "=" ~ expression ^^ {
Expand Down Expand Up @@ -483,7 +483,7 @@ class XprInt extends JavaTokenParsers with PackratParsers {
if (ops.containsKey(prec)) {
// update parser
val oldp = ops.get(prec)
ops.put(prec, (oldp._1 | parser._1, oldp._2 || parser._2))
ops.put(prec, (oldp._1 ||| parser._1, oldp._2 || parser._2))
} else {
// create a new entry in the map
ops.put(prec, parser)
Expand Down
74 changes: 68 additions & 6 deletions src/main/scala/parse/ast/Preprocessor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,78 @@ object Preprocessor {
}
sub
}
def preprocess(code: String): String = {
val si = code.indexOf(";")
val ni = code.indexOf("\n")
val i = (si, ni) match {
def minIndex(si: Int, ni: Int) = {
(si, ni) match {
case (-1, -1) => -1
case (-1, _) => ni
case (_, -1) => si
case (_, _) => Math.min(si, ni)
}
if (i == -1) preprocessLn(code)
else preprocessLn(code.substring(0, i)) + ";" + preprocess(code.substring(i + 1))
}
def preprocess(c: String, debug: Boolean = false): String = {
// You are not expected to understand what the f*ck this means.
val code = if (c.last == '\n') c else c + "\n"
var qm = false
var out = ""
var l = 0
var s = 0
if (debug) {
println("Preprocessing: ")
println(code.replaceAll("\n", ";") + "|")
}
while (l < code.length) {
val c = code.charAt(l)
if (debug) {
for (i: Int <- 0 until s) {
print(" ")
}
for (i: Int <- s until l) {
print("-")
}
println("> " + out.replaceAll("\n", ";"))
}
if (c == '\"') qm = !qm
else if (c == '\n' || (!qm && c == ';')) {
out += code.substring(s, l)
s = l
} else if (c == 'λ' && !qm) {
var lvs = 1
var index = l + 1
while (lvs != 0) {
val li = code.indexOf("λ", index)
val ei = code.indexOf("Endλ", index)
val newIndex = minIndex(li, ei)
if (newIndex != -1 && debug) {
for (i: Int <- 0 until newIndex) {
print(" ")
}
println(".")
}
if (newIndex == -1) throw new RuntimeException("unmatched lambda constructs (missing Endλ)")
else if (newIndex == li) {
index = li + 1;
lvs += 1;
} else if (newIndex == ei) {
index = Math.min(code.length, ei + 4);
lvs -= 1;
if (lvs < 0) throw new RuntimeException("unmatched lambda constructs (extra Endλ)")
} else throw new RuntimeException("I just don't know what went wrong :(")
}
// post: index holds one more than the index of the last applicable closing statement
val left = code.substring(s, l + 1)
val right = code.substring(index)
val mid = code.substring(l + 1, index - 1)
out += left + preprocess(mid) + "λ"
s = index
l = s - 1
if (debug) {
println("Preprocessing again: ")
println(code.replaceAll("\n", ";") + "|")
}
}
l += 1
}
if (debug) println(out)
out // with your memory-wasting habits!
}
}
4 changes: 3 additions & 1 deletion src/main/scala/run/RunningInstance.scala
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,9 @@ class RunningInstance(fname: String, c: RunningInstance, args: Array[Type]) {
}
if (needle >= bytecode.length - 1) isDone = true
if (!stack.isEmpty && stack.head.isInstanceOf[TError]) {
throw new RuntimeException("Runtime " + stack.head + ": " + (needle - 2).toHexString + "@" + fname)
val e = stack.head
stack = stack.tail
throw new RuntimeException("Runtime " + e + ": " + (needle - 2).toHexString + "@" + fname)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/rwvar/VariableWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ object VariableWriter {
}
def writeValToVarfile(v: Type, fn: String) {
val nf = new File(fn)
nf.mkdirs
nf.getParentFile.mkdirs
nf.createNewFile
val out = new FileOutputStream(nf)
out.write(getCA(v))
out.close
Expand Down

0 comments on commit c7b6e7f

Please sign in to comment.