Skip to content

Instantly share code, notes, and snippets.

@oguna
Last active February 4, 2016 12:52
Show Gist options
  • Select an option

  • Save oguna/31f17cb893f440c75b3c to your computer and use it in GitHub Desktop.

Select an option

Save oguna/31f17cb893f440c75b3c to your computer and use it in GitHub Desktop.
CASLⅡのパーサー
import scala.util.parsing.combinator.RegexParsers
object CaslParser extends RegexParsers {
override def skipWhitespace = false
def chrExcept(cs: Char*) = elem("", ch => cs forall (ch != _))
def label = """[A-Z][A-Z0-9]*""".r
def space = """\s+""".r
def instructionCode = "START" | "END" | "DS" | "DC" | "IN" | "OUT" | "RPUSH" | "RPOP" |
"LD" | "ST" | "LAD" | "ADDA" | "ADDL" | "SUBA" | "SUBL" | "AND" | "OR" | "XOR" | "CPA" | "CPL" | "SLA" | "SRA" |
"SLL" | "SRL" | "JPL" | "JMI" | "JNZ" | "JZE" | "JOV" | "JUMP" | "PUSH" | "POP" | "CALL" | "ERT" |
"SVC" | "NOP"
def grx = "GR0" | "GR1" | "GR2" | "GR3" | "GR4" | "GR5" | "GR6" | "GR7"
def digitLit = """\d+""".r
def hexLit = """#[A-F0-9]+""".r
def strLit = elem('\'') ~ rep(chrExcept('\'') | "''") ~ elem('\'')
def addressLit = label
def literal = digitLit | hexLit | strLit | addressLit
def arg = grx | opt(elem('=')) ~ literal
def operand = repsep(arg, elem(','))
def comment = """.*""".r
def instructionLineWithOperand =
opt(label) ~ space ~ instructionCode ~ space ~ operand ~ opt(space ~ opt(comment))
def instructionLineWithoutOperand =
opt(label) ~ space ~ instructionCode ~ opt(space ~ opt(elem(';') ~ opt(comment)))
def instructionLine = instructionLineWithOperand | instructionLineWithoutOperand
def annotationLine = opt(space) ~ elem(';') ~ comment
def line = annotationLine | instructionLine
def apply(input: String) = parseAll(line, input) match {
case Success(result, _) => result
case failure: NoSuccess => scala.sys.error(failure.msg)
}
}
import scala.util.parsing.combinator.RegexParsers
case class Instruction(label:Option[String], operator:String, operand:Seq[InstructionArgument])
abstract class InstructionArgument() {
def chars: String
}
case class Grx(chars: String) extends InstructionArgument
case class NumberLiteral(chars: String) extends InstructionArgument
case class StringLiteral(chars: String) extends InstructionArgument
case class AddressLiteral(chars: String) extends InstructionArgument
case class LiteralLiteral(ia: InstructionArgument) extends InstructionArgument {
def chars = ia.chars
}
object CaslParser extends RegexParsers {
override def skipWhitespace = false
def chrExcept(cs: Char*) = elem("", ch => cs forall (ch != _))
def label = """[A-Z][A-Z0-9]*""".r
def space = """\s+""".r
def instructionCode = "START" | "END" | "DS" | "DC" | "IN" | "OUT" | "RPUSH" | "RPOP" |
"LD" | "ST" | "LAD" | "ADDA" | "ADDL" | "SUBA" | "SUBL" | "AND" | "OR" | "XOR" | "CPA" | "CPL" | "SLA" | "SRA" |
"SLL" | "SRL" | "JPL" | "JMI" | "JNZ" | "JZE" | "JOV" | "JUMP" | "PUSH" | "POP" | "CALL" | "ERT" |
"SVC" | "NOP"
def grx:Parser[InstructionArgument] = ("GR0" | "GR1" | "GR2" | "GR3" | "GR4" | "GR5" | "GR6" | "GR7") ^^ { Grx(_)}
def digitLit:Parser[InstructionArgument] = """\d+""".r ^^ { NumberLiteral(_)}
def hexLit:Parser[InstructionArgument] = """#[A-F0-9]+""".r ^^ { NumberLiteral(_)}
def strLit:Parser[InstructionArgument] = elem('\'') ~> rep(chrExcept('\'') | "''" ^^ {e => '\''} ) <~ elem('\'') ^^ { e => StringLiteral(e.mkString) }
def addressLit:Parser[InstructionArgument] = label ^^ { AddressLiteral(_) }
def literal:Parser[InstructionArgument] = digitLit | hexLit | strLit | addressLit | grx
def literalliteral:Parser[InstructionArgument] = opt(elem('=')) ~ literal ^^ {
case (e~ l) => e match { case Some(_) => LiteralLiteral(l) case None => LiteralLiteral(l)}
}
def arg:Parser[InstructionArgument] = grx | literal
def operand:Parser[Seq[InstructionArgument]] = repsep(arg, elem(','))
def comment = """.*""".r
def instructionLineWithOperand:Parser[Instruction] =
opt(label) ~ space ~ instructionCode ~ space ~ operand <~ opt(space ~ opt(comment)) ^^ {
case (l ~ s1 ~ ic ~ s2 ~ o) => Instruction(l, ic, o)
}
def instructionLineWithoutOperand:Parser[Instruction] =
opt(label) ~ space ~ instructionCode <~ opt(space ~ opt(elem(';') ~ opt(comment))) ^^ {
case (l ~ s1 ~ ic) => Instruction(l, ic, Seq.empty[InstructionArgument])
}
def instructionLine:Parser[Instruction] = instructionLineWithOperand | instructionLineWithoutOperand
def annotationLine = opt(space) ~ elem(';') ~ comment
def line:Parser[Option[Instruction]] = annotationLine ^^ { e => Option.empty[Instruction] } | instructionLine ^^ {Option(_)}
def apply(input: String) = parseAll(line, input) match {
case Success(result, _) => result
case failure: NoSuccess => scala.sys.error(failure.msg)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment