Last active
June 24, 2016 05:30
-
-
Save hsk/04d0e9aa259f8f7a0b832c4dfe8c53b0 to your computer and use it in GitHub Desktop.
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
# Klassic言語仕様 | |
## Klassicの開発ポリシー | |
基本的にScalaを改良しつつ、最初はコアな機能を作成し、パーシャルファンクション等の細かい機能は後からつける。 | |
EOF ::= not(elem(".", (ch: Char) => ch != CharSequenceReader.EofCh), "EOF Expected") | |
LINEFEED ::= ("\r\n" | "\r" | "\n") | |
SEMICOLON ::= ";" | |
ANY ::= elem(".", (ch: Char) => ch != CharSequenceReader.EofCh) | |
SPACING ::= (COMMENT | "\r\n" | "\r" | "\n" | " " | "\t" | "\b" | "\f")* | |
SPACING_WITHOUT_LF ::= (COMMENT | "\t" | " " | "\b" | "\f")* | |
TERMINATOR ::= (LINEFEED | SEMICOLON | EOF) SPACING | |
SEPARATOR ::= (LINEFEED | COMMA | EOF | SPACING_WITHOUT_LF) SPACING | |
## コメント | |
BLOCK_COMMENT ::= "/*" (not("*/") (BLOCK_COMMENT | ANY))* "*/" | |
LINE_COMMENT ::= "//" (not(LINEFEED) ANY)* LINEFEED | |
COMMENT ::= BLOCK_COMMENT | LINE_COMMENT | |
コメントは、ブロックコメントと一行コメントがあります。ブロックコメントはネストすることが可能です。 | |
## 演算子 | |
LT ::= "<" | |
GT ::= ">" | |
LTE ::= "<=" | |
GTE ::= ">=" | |
PLUS ::= "+" | |
MINUS ::= "-" | |
ASTER ::= "*" | |
SLASH ::= "/" | |
## 括弧 | |
LPAREN ::= "(" | |
RPAREN ::= ")" | |
LBRACE ::= "{" | |
RBRACE ::= "}" | |
LBRACKET ::= "[" | |
RBRACKET ::= "]" | |
COMMA ::= "," | |
DOT ::= "." | |
EQ ::= "=" | |
EQEQ ::= "==" | |
ARROW ::= "=>" | |
COLON ::= ":" | |
QUES ::= "?" | |
AMP2 ::= "&&" | |
BAR2 ::= "||" | |
## キーワード | |
IF ::= "if" | |
ELSE ::= "else" | |
WHILE ::= "while" | |
FOREACH ::= "foreach" | |
IMPORT ::= "import" | |
TRUE ::= "true" | |
FALSE ::= "false" | |
IN ::= "in" | |
CLASS ::= "class" | |
DEF ::= "def" | |
VAL ::= "val" | |
NEW ::= "new" | |
# 型 | |
typeAnnotation ::= ":" ("Byte" | "Short" | "Int" | "Long" | "Float" | "Double" | "Boolean" | "Unit" | "?" | "*") | |
現状はユーザー定義型はなくて考え中 | |
Scalaのsealed class,trait case classをもっと短く書けるようにする | |
program ::= SPACING repsep(import TERMINATOR) (lines opt(TERMINATOR)) | |
import ::= IMPORT fqcn | |
lines ::= SPACING repsep(line, TERMINATOR) opt(TERMINATOR) | |
line ::= expression | val_declaration | functionDefinition | |
expression ::= assignment | logical | ifExpression | whileExpression | foreachExpression | |
//if ::= "if" "(" expression ")" expression "else" expression | |
ifExpression ::= IF LPAREN expression RPAREN expression ELSE expression | |
//while ::= "while" "(" expression ")" expression | |
whileExpression ::= WHILE LPAREN expression RPAREN expression | |
//foreach ::= "foreach" "(" ident "in" expression ")" expression | |
foreachExpression ::= FOREACH LPAREN ident IN expression RPAREN expression | |
logical ::= chainl1(conditional, AMP2 | BAR2) | |
//conditional ::= add {"<" add | ">" add | "<=" add | ">=" add} | |
conditional ::= chainl1(add, EQEQ | LTE | GTE | LT | GT) | |
//add ::= term {"+" term | "-" term} | |
add ::= chainl1(term, PLUS | MINUS)) | |
//term ::= factor {"*" factor | "/" factor} | |
term ::= chainl1(unary, ASTER | SLASH) | |
unary ::= (MINUS unary | PLUS unary | invocation) | |
invocation ::= application DOT ident opt(LPAREN repsep(expression, COMMA) RPAREN)* | |
application ::= primary opt(LPAREN repsep(expression, COMMA) SPACING RPAREN) | |
//primary ::= intLiteral | stringLiteral | listLiteral | "(" expression ")" | "{" lines "}" | |
primary ::= ident | floatLiteral | integerLiteral | stringLiteral | listLiteral | newObject | anonymousFunction | LPAREN expression RPAREN | LBRACE lines RBRACE | hereDocument | |
## 整数 | |
//intLiteral ::= ["1"-"9"] {"0"-"9"} | |
integerLiteral ::= ("""[1-9][0-9]*|0""" opt("BY"| "L" | "S") | |
## 浮動小数点数 | |
floatLiteral ::= ("([1-9][0-9]*|0)\\.[0-9]*".r opt("F")) | |
## ブーリアン | |
booleanLiteral ::= (TRUE | FALSE) | |
## 文字列 | |
//stringLiteral ::= "\"" ((?!")(\[rntfb"'\\]|[^\\]))* "\"" | |
stringLiteral ::= | |
("\"" ~> | |
(% ~ """((?!("|#\{))(\\[rntfb"'\\]|[^\\]))+""".r ^^ {case location ~ in => | |
StringNode(location, unescape(in)) | |
} | "#{" ~> expression <~ "}" | |
).* | |
<~ "\"" ^^ { values => | |
values.foldLeft(StringNode(NoLocation, ""):AstNode) { (node, content) => BinaryExpression(content.location, Operator.ADD, node, content) } | |
}) <~ SPACING_WITHOUT_LF | |
listLiteral ::= Parser[AstNode] = LBRACKET repsep(expression, SEPARATOR) opt(SEPARATOR) RBRACKET | |
fqcn ::= ident (DOT ident)* | |
oneLine ::= regex(""".*(\r\n|\r|\n|$)""".r) | |
hereDocument ::= ("""<<[a-zA-Z_][a-zA-Z0-9_]*""".r >> { t => | |
val tag = t.substring(2) | |
Parser{in => | |
val Success(temp, rest) = oneLine(in) | |
val line = new CharSequenceReader(temp, 0) | |
hereDocumentBody(tag).apply(rest) match { | |
case Success(value, next) => | |
val source = cat(line, next) | |
Success(StringNode(NoLocation, value), source) | |
case Failure(msg, next) => Failure(msg, cat(line, next)) | |
case Error(msg, next) => Error(msg, cat(line, next)) | |
} | |
} | |
}) <~ SPACING_WITHOUT_LF | |
def hereDocumentBody(beginTag: String): Parser[String] = oneLine >> {line => | |
if(beginTag == line.trim) "" else hereDocumentBody(beginTag) ^^ {result => | |
line + result | |
} | |
} | |
ident ::= """[A-Za-z_][a-zA-Z0-9]*"""r | |
assignment ::= ident EQ expression | |
// val_declaration ::= "val" ident "=" expression | |
val_declaration ::= (VAL ident opt(typeAnnotation) EQ expression | |
// anonnymousFunction ::= "(" [param {"," param}] ")" "=>" expression | |
anonymousFunction ::= opt(LPAREN repsep(ident opt(typeAnnotation), COMMA) RPAREN) ARROW expression | |
// newObject ::= "new" fqcn "(" [param {"," param} ")" | |
newObject ::= NEW fqcn opt(LPAREN repsep(ident, COMMA) RPAREN) | |
## 関数定義 | |
// functionDefinition ::= "def" ident ["(" [param {"," param]] ")"] "=" expression | |
functionDefinition ::= DEF ident opt(LPAREN repsep(ident opt(typeAnnotation), COMMA) RPAREN opt(typeAnnotation) EQ expression | |
defから始まる。 | |
parse ::= lines |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment