Last active
February 4, 2016 12:52
-
-
Save oguna/31f17cb893f440c75b3c to your computer and use it in GitHub Desktop.
CASLⅡのパーサー
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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