Compare commits

...

19 커밋

작성자 SHA1 메시지 날짜
  MaximeBarniaudy c2da606329 Migrate everything to peg vm 10 달 전
  MaximeBarniaudy 06962d9a48 add do-while and f-string dynamic addition proofs of concepts 10 달 전
  MaximeBarniaudy 168631e246 Add emitByteCode functions to support using the peg VM, add support for @ actions, automatically generate the minproto.grammar file from minproto.leg and use that in the parser generator. Fix issue with backslashes being stupid. 10 달 전
  MaximeBarniaudy c3125a863f Move side effect of variable assignment in namespace out of grammar for logic and ease of use reasons 11 달 전
  MaximeBarniaudy 959c34b7b2 Remove old unused code, and measure parsing speed 11 달 전
  MaximeBarniaudy 3ef49024c5 Use newest primitives for character class and string matching 11 달 전
  MaximeBarniaudy b2e4198529 Build Grammar objects whose methods are expression representations of grammar rules 11 달 전
  MaximeBarniaudy d26d33bf3f Fix errors after SetVar behavior change and let removal 11 달 전
  MaximeBarniaudy d840010b55 Delare Stream object in C code and add primitive for stream string matching. Also refactor the rollback mechanism in the grammar parser to give responsibility to the right object. 11 달 전
  MaximeBarniaudy 090142c69c Make grammar_parser.meta use the entire grammar from minproto.leg 11 달 전
  MaximeBarniaudy b23a65dbb0 Add optional base argument to String.asInteger 11 달 전
  MaximeBarniaudy 1a7d31d66e Fix error after single quote semantics change 11 달 전
  MaximeBarniaudy a5b9103da3 Add with and without functions for namespace manimulation, add namespace support to grammars, add test of parser circularity 1 년 전
  MaximeBarniaudy 1ec2c7d8ef parser circularity 1 년 전
  MaximeBarniaudy dfa680df47 dotdot got lost in merging 1 년 전
  MaximeBarniaudy 9851f982cb Add Invoke and GetProp 1 년 전
  MaximeBarniaudy 4eeaa54367 Minimal grammar parsing 1 년 전
  MaximeBarniaudy d170f243ee Add an intern primitive for symbol creation 1 년 전
  WitherFlower 561c1dcb80 Merge range access and grammar parser changes 1 년 전
10개의 변경된 파일2508개의 추가작업 그리고 25개의 파일을 삭제
분할 보기
  1. +4
    -1
      Makefile
  2. +53
    -0
      dowhile.meta
  3. +81
    -0
      fstring.meta
  4. +1437
    -0
      grammar_parser.meta
  5. +316
    -0
      minproto.grammar
  6. +180
    -24
      minproto.leg
  7. +73
    -0
      rawMetaGrammar.leg
  8. +83
    -0
      rawgrammar.leg
  9. +275
    -0
      rawminproto.leg
  10. +6
    -0
      test.txt

+ 4
- 1
Makefile 파일 보기

@ -15,7 +15,7 @@ MAIN = minproto
all : $(MAIN)
% : %.c
% : %.c %.grammar
$(CC) $(GFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
%-opt : %.c
@ -27,6 +27,9 @@ all : $(MAIN)
%.c : %.leg
leg -o $@ $<
%.grammar : %.leg
( sed "/%{/,/%}/d" $< | sed "/%%/,\$$d" ) > $@
tests : .FORCE
$(MAKE) clean all GFLAGS="-Wno-unused -g -DTYPECODES=1 -DELOPT=1"
-./$(MAIN) test.txt > test.out 2>&1

+ 53
- 0
dowhile.meta 파일 보기

@ -0,0 +1,53 @@
Do = Object.subtype(#Do);
Do.new(body, cond) {
self = super.new();
self.body = body;
self.cond = cond;
self;
}
Do.__eval__(env) {
local result = self.body.__eval__(env);
while (self.cond.__eval__(env)) {
result = self.body.__eval__(env);
}
result;
}
Do.__codeon__(str) {
str.push("do ");
self.body.__codeon__(str);
str.push(" while ( ");
self.cond.__codeon__(str);
str.push(" )");
}
// parse the grammar expression
// put it at the beginning of stmt (which is an alternation)
metaGrammar.stmt.prepend("\"whatever i want\" - b:stmt WHILE LPAREN c:expr RPAREN EOS { $$ = Do.new(b, c); }");
{
local i = 1;
{
whatever i want {
i *= 2;
print(i, "\n");
} while (i < 1000);
whatever i want {
i *= 2;
print(i, "\n");
} while (i < 1000);
whatever i want {
i *= 2;
print(i, "\n");
} while (i < 1000);
}
}

+ 81
- 0
fstring.meta 파일 보기

@ -0,0 +1,81 @@
FormatString = Object.subtype(#FormatString);
FormatString.new(elements) {
self = super.new();
self.elements = elements;
self;
}
FormatString.__eval__(env) {
local result = "";
for(elem in self.elements) {
local elemval = elem.__eval__(env);
if (elemval.__name__ == #String) {
result.push(elemval);
} else {
elemval.__codeon__(result);
}
}
result;
}
FormatString.__codeon__(str) {
str.push("f\"");
for(elem in self.elements) {
if (elem.__name__ == #String) {
str.push(elem.escaped());
} else {
str.push("$");
elem.__codeon__(str);
}
}
str.push("\"");
}
nonSpaceEatingId = parseDefinition(
"nonSpaceEatingId = < LETTER ALNUM* > { $$ = intern(yytext) }
");
nonSpaceEatingBlock = parseDefinition(
"nonSpaceEatingBlock = LBRACE b:mkobj
( e:stmt { $$ = b.push(e) }
)* \"}\" { $$ = b }
");
fStringChar = parseDefinition(
"fStringChar = < (!\"\\\"\" !\"$\" char )+ > { $$ = yytext.unescaped() }
| \"\\\\$\" { $$ = \"$\" }
");
fStringRule = parseDefinition(
"fstring = \"f\\\"\" elements:mkobj
( \"$\" i:nonSpaceEatingId { $$ = elements.push(GetVar.new(name: i)) }
| \"$\" b:nonSpaceEatingBlock { $$ = elements.push(Block.new(body: b)) }
| c:fStringChar { $$ = elements.push(c) }
)* \"\\\"\" { $$ = FormatString.new(elements) }
");
// regenerate the expression to be executed
metaGrammar.addRule(nonSpaceEatingBlock.name, nonSpaceEatingBlock.expression);
metaGrammar.addRule(nonSpaceEatingId.name, nonSpaceEatingId.expression);
metaGrammar.addRule(fStringChar.name, fStringChar.expression);
metaGrammar.addRule(fStringRule.name, fStringRule.expression);
metaGrammar.primary.prepend("fstring");
formatInt(integer) {
if (integer > 1000) {
return f"${formatInt((integer - integer % 1000) / 1000)},${integer % 1000}";
}
return f"$integer";
}
a = 69;
print(f"Reimu has $a power and ${6*7} point items and \$${ formatInt(1 << 32) } money.\n");
n = 100;
print(f"Sum of integers from 1 to $n : ${local sum = 0; for (i in n + 1) sum += i}\n");
print(f"${formatInt.function}\n");
//{
// print(f"${__env__()}\n");
//}

+ 1437
- 0
grammar_parser.meta
파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
파일 보기


+ 316
- 0
minproto.grammar 파일 보기

@ -0,0 +1,316 @@
# minproto.leg -- minimal prototype langauge for semantic experiments
#
# last edited: 2024-07-10 11:28:02 by piumarta on zora-1034.local
start = - ( s:stmt { global yysval = s }
| !. { global yysval = 0 }
| < (!EOL .)* > { syntaxError(yytext) }
)
stmt = WHILE LPAREN c:expr RPAREN s:stmt { $$ = newWhile(c, s) }
| IF LPAREN c:expr RPAREN s:stmt
( ELSE t:stmt { $$ = newIf(c, s, t ) }
| { $$ = newIf(c, s, nil) }
)
| CONT EOS { $$ = newContinue() }
| BREAK e:expr EOS { $$ = newBreak(e) }
| BREAK EOS { $$ = newBreak(nil) }
| RETURN e:expr EOS { $$ = newReturn(e) }
| RETURN EOS { $$ = newReturn(nil) }
| FOR LPAREN i:id IN e:expr RPAREN
s:stmt { $$ = newForIn(i, e, s) }
| FOR LPAREN i:id FROM a:expr
TO b:expr RPAREN s:stmt { $$ = newForFromTo(i, a, b, s) }
| FOR LPAREN i:expr SEMI c:expr SEMI
u:expr RPAREN s:stmt { $$ = newFor(i, c, u, s) }
| TRY t:stmt
( CATCH LPAREN i:id RPAREN c:stmt { $$ = newTryCatch(t, i, c) }
| ENSURE e:stmt { $$ = newTryEnsure(t, e) }
)
| RAISE e:expr EOS { $$ = newRaise(e) }
| LOCAL i:id p:params b:block { $$ = newSetLocal (i, newLambda(p, b, nil, i)) }
| GLOBAL i:id p:params b:block { $$ = newSetGlobal(i, newLambda(p, b, nil, i)) }
| i:id p:params b:block { $$ = newSetVar (i, newLambda(p, b, nil, i)) }
| v:proto DOT i:id p:params b:block { $$ = newSetProp(v, i, newLambda(p, b, v, i)) }
| b:block { $$ = newBlock(b) }
| e:expr EOS { $$ = e }
proto = v:var ( DOT j:id !LPAREN { v = newGetProp(v, j) }
)* { $$ = v }
EOS = SEMI+ | &RBRACE | &ELSE | &CATCH
expr = LOCAL i:id ASSIGN e:expr { $$ = newSetLocal (i, e) }
| GLOBAL i:id ASSIGN e:expr { $$ = newSetGlobal(i, e) }
| i:id ASSIGN e:expr { $$ = newSetVar (i, e) }
| l:logor ( ASSIGN r:expr { l = assign(l, r) }
| PLUSEQ r:expr { l = newBinop(opPreAdd, lvalue(l), r) }
| MINUSEQ r:expr { l = newBinop(opPreSub, lvalue(l), r) }
| STAREQ r:expr { l = newBinop(opPreMul, lvalue(l), r) }
| SLASHEQ r:expr { l = newBinop(opPreDiv, lvalue(l), r) }
| PCENTEQ r:expr { l = newBinop(opPreMod, lvalue(l), r) }
| SHLEQ r:expr { l = newBinop(opPreShl, lvalue(l), r) }
| SHREQ r:expr { l = newBinop(opPreShr, lvalue(l), r) }
| ANDEQ r:expr { l = newBinop(opPreAnd, lvalue(l), r) }
| XOREQ r:expr { l = newBinop(opPreXor, lvalue(l), r) }
| OREQ r:expr { l = newBinop(opPreOr, lvalue(l), r) }
)? { $$ = l }
logor = l:logand ( BARBAR r:logand { l = newBinop(opLogOr, l, r) }
)* { $$ = l }
logand = l:bitor ( ANDAND r:bitor { l = newBinop(opLogAnd, l, r) }
)* { $$ = l }
bitor = l:bitxor ( OR r:bitxor { l = newBinop(opBitOr, l, r) }
)* { $$ = l }
bitxor = l:bitand ( XOR r:bitand { l = newBinop(opBitXor, l, r) }
)* { $$ = l }
bitand = l:eq ( AND r:eq { l = newBinop(opBitAnd, l, r) }
)* { $$ = l }
eq = l:ineq ( EQ r:ineq { l = newBinop(opEq, l, r) }
| NOTEQ r:ineq { l = newBinop(opNotEq, l, r) }
)* { $$ = l }
ineq = l:shift ( LESS r:shift { l = newBinop(opLess, l, r) }
| LESSEQ r:shift { l = newBinop(opLessEq, l, r) }
| GRTREQ r:shift { l = newBinop(opGrtrEq, l, r) }
| GRTR r:shift { l = newBinop(opGrtr, l, r) }
)* { $$ = l }
shift = l:sum ( SHL r:sum { l = newBinop(opShl, l, r) }
| SHR r:sum { l = newBinop(opShr, l, r) }
)* { $$ = l }
sum = l:prod ( PLUS r:prod { l = newBinop(opAdd, l, r) }
| MINUS r:prod { l = newBinop(opSub, l, r) }
)* { $$ = l }
prod = l:prefix ( STAR r:prefix { l = newBinop(opMul, l, r) }
| SLASH r:prefix { l = newBinop(opDiv, l, r) }
| PCENT r:prefix { l = newBinop(opMod, l, r) }
) * { $$ = l }
prefix = PPLUS p:prefix { $$ = newBinop(opPreAdd, lvalue(p), newInteger(1)) }
| MMINUS p:prefix { $$ = newBinop(opPreSub, lvalue(p), newInteger(1)) }
| PLING p:prefix { $$ = newUnyop(opNot, p) }
| MINUS p:prefix { $$ = newUnyop(opNeg, p) }
| TILDE p:prefix { $$ = newUnyop(opCom, p) }
| BQUOTE s:stmt { $$ = newUnyop(opQuasiquote, s) }
| COMMAT e:expr { $$ = newUnyop(opUnquote, e) }
| postfix
postfix = SUPER DOT i:id a:args { $$ = newSuper(i, a) }
| p:primary
( LBRAK
( COLON ( RBRAK { p = newGetSlice(p, nil, nil) }
| e:xexpr RBRAK { p = newGetSlice(p, nil, e) }
)
| s:xexpr ( COLON ( RBRAK { p = newGetSlice(p, s, nil) }
| e:xexpr RBRAK { p = newGetSlice(p, s, e) }
)
| RBRAK { p = newGetArray(p, s) }
)
)
| DOT i:id ( a:args !LBRACE { p = newInvoke(p, i, a) }
| { p = newGetProp(p, i) }
)
| a:args !LBRACE { p = newApply(p, a) }
)*
( PPLUS { p = newBinop(opPostAdd, lvalue(p), newInteger( 1)) }
| MMINUS { p = newBinop(opPostAdd, lvalue(p), newInteger(-1)) }
)? { $$ = p }
args = LPAREN a:mkobj
( RPAREN
| ( k:id COLON e:xexpr { Object_put(a, k, e) }
| e:xexpr { Object_push(a, e) }
)
( COMMA ( k:id COLON e:xexpr { Object_put(a, k, e) }
| e:xexpr { Object_push(a, e) }
) )* RPAREN ) { $$ = a }
params = LPAREN p:mkobj
( RPAREN
| i:id ( COLON e:expr { Object_put(p, i, e) }
| { Object_push(p, i) }
)
( COMMA i:id ( COLON e:expr { Object_put(p, i, e) }
| { Object_push(p, i) }
)
)* RPAREN ) { $$ = p }
mkobj = { $$ = (global new)(pObject) }
primary = nil | number | string | symbol | var | lambda | subexpr | literal # | regex
lambda = p:params b:block { $$ = newLambda(p, b, nil, nil) }
subexpr = LPAREN e:expr RPAREN { $$ = e }
| b:block { $$ = newBlock(b) }
literal = LBRAK o:mkobj
( RBRAK
| ( ( i:id COLON e:expr { Object_put(o, i, e) }
| e:expr { Object_push(o, e) }
) ( COMMA ( i:id COLON e:expr { Object_put(o, i, e) }
| e:expr { Object_push(o, e) }
) )* )? RBRAK ) { $$ = newLiteral(o) }
block = LBRACE b:mkobj
( e:stmt { Object_push(b, e) }
)* ( RBRACE { $$ = b }
| error @{ expected("statement or \x7D", yytext) }
)
nil = NIL { $$ = nil }
number = "-" n:unsign { $$ = neg(n) }
| "+" n:number { $$ = n }
| n:unsign { $$ = n }
unsign = < DIGIT* '.' DIGIT+ EXP? > - { $$ = newFloat(strtod(yytext, 0)) }
| "0" [bB] < BIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 2)) }
| "0" [xX] < HIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 16)) }
| "0" < OIGIT* > - { $$ = newInteger(strtol(yytext, 0, 8)) }
| < DIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 10)) }
| "'" < char > "'" - { $$ = newInteger(_get(newStringUnescaped(yytext), String,value)[0]) }
string = '"' < ( !'"' char )* > '"' - { $$ = newStringUnescaped(yytext) }
char = '\\' [abefnrtv'"\[\]\\]
| '\\' [0-3][0-7][0-7]
| '\\' [xX] HIGIT*
| '\\' [0-7][0-7]?
| !'\\' .
# char = "\\" ( ["'\\abfnrtv]
# | [xX] HIGIT*
# | [0-7][0-7]?[0-7]?
# )
# | .
symbol = HASH i:id { $$ = i }
var = LOCAL i:id { $$ = newGetLocal (i) }
| GLOBAL i:id { $$ = newGetGlobal(i) }
| i:id { $$ = newGetVar (i) }
id = < LETTER ALNUM* > - { $$ = intern(yytext) }
# regex = SLASH a:alts SLASH { $$ = a }
# alts = s:seq ( OR t:seq { s = Alt_append(t) }
# )* { $$ = s }
# seq = p:pre ( q:pre { s = Seq_append(t) }
# )* { $$ = s }
# elt = action | pre
# action = b:block { $$ = newAction(b) }
# pre = PLING p:pre { $$ = newNot(p) }
# | AND p:pre { $$ = newAnd(p) }
# | post
# post = a:atom ( STAR { a = newMany(a) }
# | PLUS { a = newMore(a) }
# | QUERY { a = newMore(a) }
# )? { $$ = a }
# atom = DOT { $$ = newDot() }
# | "[" ( !"]" "\\"? . )* "]" - { $$ = newClass(yytext) }
# | '"' xxxxxx
# class = LBRAK
BIGIT = [0-1]
OIGIT = [0-7]
DIGIT = [0-9]
HIGIT = [0-9A-Fa-f]
LETTER = [A-Za-z_$?]
ALNUM = LETTER | DIGIT
SIGN = [-+]
EXP = [eE] SIGN DIGIT+
- = SPACE*
SPACE = [ \t] | EOL | SLC | MLC
EOL = [\n\r] { ++lineno }
SLC = "//" (!EOL .)*
MLC = "/*" ( MLC | !"*/" (EOL | .))* "*/" -
NIL = "nil" !ALNUM -
WHILE = "while" !ALNUM -
IF = "if" !ALNUM -
ELSE = "else" !ALNUM -
FOR = "for" !ALNUM -
IN = "in" !ALNUM -
FROM = "from" !ALNUM -
TO = "to" !ALNUM -
CONT = "continue" !ALNUM -
BREAK = "break" !ALNUM -
RETURN = "return" !ALNUM -
TRY = "try" !ALNUM -
CATCH = "catch" !ALNUM -
ENSURE = "ensure" !ALNUM -
RAISE = "raise" !ALNUM -
GLOBAL = "global" !ALNUM -
LOCAL = "local" !ALNUM -
SUPER = "super" !ALNUM -
BQUOTE = "`" -
COMMAT = "@" -
HASH = "#" -
SEMI = ";" -
ASSIGN = "=" ![=] -
COMMA = "," -
COLON = ":" ![:] -
LPAREN = "(" -
RPAREN = ")" -
LBRAK = "[" -
RBRAK = "]" -
LBRACE = "{" -
RBRACE = "}" -
BARBAR = "||" ![=] -
ANDAND = "&&" ![=] -
OR = "|" ![|=] -
OREQ = "|=" -
XOR = "^" ![=] -
XOREQ = "^=" -
AND = "&" ![&=] -
ANDEQ = "&=" -
EQ = "==" -
NOTEQ = "!=" -
LESS = "<" ![<=] -
LESSEQ = "<=" -
GRTREQ = ">=" -
GRTR = ">" ![=] -
SHL = "<<" ![=] -
SHLEQ = "<<=" -
SHR = ">>" ![=] -
SHREQ = ">>=" -
PLUS = "+" ![+=] -
PLUSEQ = "+=" -
PPLUS = "++" -
MINUS = "-" ![-=] -
MINUSEQ = "-=" -
MMINUS = "--" -
STAR = "*" ![=] -
STAREQ = "*=" -
SLASH = "/" ![/=] -
SLASHEQ = "/=" -
PCENT = "%" ![=] -
PCENTEQ = "%=" -
DOT = "." ![.] -
PLING = "!" ![=] -
TILDE = "~" -
error = - < (!EOL .)* >
xexpr = expr | error @{ expected("expression", yytext) }

+ 180
- 24
minproto.leg 파일 보기

@ -121,9 +121,9 @@ oop printOn(oop buf, oop obj, int indent);
#endif
#if PRIMCLOSURE
#define doProtos(_) _(Object) _(RefLocal) _(GetLocal) _(SetLocal) _(RefGlobal) _(GetGlobal) _(SetGlobal) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(GetSlice) _(Call) _(Invoke) _(Super) _(Continue) _(Break) _(Return) _(TryCatch) _(TryEnsure)_(Raise)_(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal)
#define doProtos(_) _(Object) _(RefLocal) _(GetLocal) _(SetLocal) _(RefGlobal) _(GetGlobal) _(SetGlobal) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(GetSlice) _(Call) _(Invoke) _(Super) _(Continue) _(Break) _(Return) _(TryCatch) _(TryEnsure)_(Raise)_(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Stream)
#else
#define doProtos(_) _(Object) _(RefLocal) _(GetLocal) _(SetLocal) _(RefGlobal) _(GetGlobal) _(SetGlobal) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(GetSlice) _(Call) _(Invoke) _(Super) _(Continue) _(Break) _(Return) _(TryCatch) _(TryEnsure) _(Raise) _(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure)
#define doProtos(_) _(Object) _(RefLocal) _(GetLocal) _(SetLocal) _(RefGlobal) _(GetGlobal) _(SetGlobal) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(GetSlice) _(Call) _(Invoke) _(Super) _(Continue) _(Break) _(Return) _(TryCatch) _(TryEnsure) _(Raise) _(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure) _(Stream)
#endif
#define declareProto(NAME) oop p##NAME = 0;
@ -147,7 +147,7 @@ doTypes(makeProto);
doProperties(declareProp);
#undef declareProp
#define doSymbols(_) _(t) _(name) _(expr) _(function) _(arguments) _(object) _(index) _(key) _(value) _(self) _(method) _(parameters) _(body) _(lambda) _(environment) _(operation) _(full) _(condition) _(consequent) _(alternate) _(expression) _(identifier) _(initialise) _(update) _(first) _(last) _(fixed) _(keyvals) _(__namespaces__) _(O) _(d) _(p) _(v) _(statement) _(handler) _(kind) _(message) _(operand1) _(operand2) _(profile) _(parent) _(count) _(stamp) _(time) _(start) _(stop) _($$) _(yytext) _(yyleng)
#define doSymbols(_) _(t) _(name) _(expr) _(function) _(arguments) _(object) _(index) _(key) _(value) _(self) _(method) _(parameters) _(body) _(lambda) _(environment) _(operation) _(full) _(condition) _(consequent) _(alternate) _(expression) _(identifier) _(initialise) _(update) _(first) _(last) _(fixed) _(keyvals) _(__namespaces__) _(O) _(d) _(p) _(v) _(statement) _(handler) _(kind) _(message) _(operand1) _(operand2) _(profile) _(parent) _(count) _(stamp) _(time) _(start) _(stop) _($$) _(yytext) _(yyleng) _(env) _(content) _(position) _(limit) _(lastBegin)
#define declareSym(NAME) oop sym_##NAME = 0;
doSymbols(declareSym);
@ -501,6 +501,8 @@ oop newStringUnescaped(char *string)
case 'r' : c = '\r'; break;
case 't' : c = '\t'; break;
case 'v' : c = '\v'; break;
case '[' : c = '[' ; break;
case ']' : c = ']' ; break;
case 'X' :
case 'x' : c = readCharValue(&string, 16, -1); break;
case '0'...'7': --string; c = readCharValue(&string, 8, 3); break;
@ -3340,6 +3342,26 @@ void Literal_codeOn(oop exp, oop str, oop env)
# endif
}
oop newStream(oop content)
{
oop o = new(pStream);
Object_put(o, sym_content , content);
Object_put(o, sym_position , newInteger(0));
Object_put(o, sym_limit , newInteger(_get(content, String, length)));
Object_put(o, sym_lastBegin, newInteger(0));
return o;
}
oop Stream_eval(oop exp, oop env)
{
return exp;
}
void Stream_codeOn(oop exp, oop str, oop env)
{
Object_codeOn(exp, str, env);
}
oop lvalue(oop rval)
{
if (!is(Object,rval)) valueError("=", "non-assignable value", rval);
@ -3372,10 +3394,12 @@ void expected(char *what, char *where)
fatal("syntax error: %s expected near: %s", what, where);
}
#define global
%}
start = - ( s:stmt { yysval = s }
| !. { yysval = 0 }
start = - ( s:stmt { global yysval = s }
| !. { global yysval = 0 }
| < (!EOL .)* > { syntaxError(yytext) }
)
@ -3461,10 +3485,10 @@ sum = l:prod ( PLUS r:prod { l = newBinop(opAdd, l, r) }
| MINUS r:prod { l = newBinop(opSub, l, r) }
)* { $$ = l }
prod = l:prefix ( STAR r:prefix { l = newBinop(opMul, l, r) }
| SLASH r:prefix { l = newBinop(opDiv, l, r) }
| PCENT r:prefix { l = newBinop(opMod, l, r) }
)* { $$ = l }
prod = l:prefix ( STAR r:prefix { l = newBinop(opMul, l, r) }
| SLASH r:prefix { l = newBinop(opDiv, l, r) }
| PCENT r:prefix { l = newBinop(opMod, l, r) }
) * { $$ = l }
prefix = PPLUS p:prefix { $$ = newBinop(opPreAdd, lvalue(p), newInteger(1)) }
| MMINUS p:prefix { $$ = newBinop(opPreSub, lvalue(p), newInteger(1)) }
@ -3515,7 +3539,7 @@ params = LPAREN p:mkobj
)
)* RPAREN ) { $$ = p }
mkobj = { $$ = new(pObject) }
mkobj = { $$ = (global new)(pObject) }
primary = nil | number | string | symbol | var | lambda | subexpr | literal # | regex
@ -3544,8 +3568,7 @@ number = "-" n:unsign { $$ = neg(n) }
| "+" n:number { $$ = n }
| n:unsign { $$ = n }
unsign = < DIGIT+ '.' DIGIT* EXP? > - { $$ = newFloat(strtod(yytext, 0)) }
| < DIGIT* '.' DIGIT+ EXP? > - { $$ = newFloat(strtod(yytext, 0)) }
unsign = < DIGIT* '.' DIGIT+ EXP? > - { $$ = newFloat(strtod(yytext, 0)) }
| "0" [bB] < BIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 2)) }
| "0" [xX] < HIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 16)) }
| "0" < OIGIT* > - { $$ = newInteger(strtol(yytext, 0, 8)) }
@ -3554,11 +3577,16 @@ unsign = < DIGIT+ '.' DIGIT* EXP? > - { $$ = newFloat(strtod(yytext, 0
string = '"' < ( !'"' char )* > '"' - { $$ = newStringUnescaped(yytext) }
char = "\\" ( ["'\\abfnrtv]
| [xX] HIGIT*
| [0-7][0-7]?[0-7]?
)
| .
char = '\\' [abefnrtv'"\[\]\\]
| '\\' [0-3][0-7][0-7]
| '\\' [xX] HIGIT*
| '\\' [0-7][0-7]?
| !'\\' .
# char = "\\" ( ["'\\abfnrtv]
# | [xX] HIGIT*
# | [0-7][0-7]?[0-7]?
# )
# | .
symbol = HASH i:id { $$ = i }
@ -3673,7 +3701,7 @@ SLASH = "/" ![/=] -
SLASHEQ = "/=" -
PCENT = "%" ![=] -
PCENTEQ = "%=" -
DOT = "." -
DOT = "." ![.] -
PLING = "!" ![=] -
TILDE = "~" -
@ -3683,6 +3711,7 @@ xexpr = expr | error @{ expected("expression", yytext) }
%%
;
#undef global
#if PROFILE
@ -3955,6 +3984,22 @@ oop prim_Object_initialise(oop func, oop self, oop args, oop env)
return self;
}
oop prim_newBinop(oop func, oop self, oop args, oop env)
{ assert(is(Object, args));
int argc = _get(args, Object,isize);
if (argc != 3) fatal("newBinop: Expected 3 arguments, got %d\n", argc);
oop *indexed = _get(args, Object,indexed);
return newBinop(integerValue(indexed[0], "prim_newBinop"), indexed[1], indexed[2]);
}
oop prim_newApply(oop func, oop self, oop args, oop env)
{ assert(is(Object, args));
int argc = _get(args, Object,isize);
if (argc != 2) fatal("newApply: Expected 2 arguments, got %d\n", argc);
oop *indexed = _get(args, Object,indexed);
return newApply(indexed[0], indexed[1]);
}
oop prim_Object_push(oop func, oop self, oop args, oop env)
{ assert(is(Object, args));
int argc = _get(args, Object,isize); assert(is(Object, self));
@ -4008,10 +4053,21 @@ oop prim_String_pop(oop func, oop self, oop args, oop env)
}
oop prim_String_asInteger(oop func, oop self, oop args, oop env)
{ assert(is(String, self));
{ assert(is(Object, args));
int argc = _get(args, Object,isize); assert(is(String, self));
if (argc > 1) fatal("String.asInteger: expected either 0 or 1 arguments, got %d\n", argc);
char *str = String_content(self); // ensure nul terminator
char *end = 0;
long value = strtol(str, &end, 0);
long value;
if (argc == 1) {
oop base = _get(args, Object,indexed)[0];
value = strtol(str, &end, integerValue(base, "String.asInteger"));
} else {
value = strtol(str, &end, 0);
}
if (*end) return nil;
return newInteger(value);
}
@ -4243,6 +4299,47 @@ oop prim_Symbol_asString(oop func, oop self, oop args, oop env)
return newString(_get(self, Symbol,name));
}
oop prim_newStream(oop func, oop self, oop args, oop env)
{ assert(is(Object, args));
int argc = _get(args, Object,isize);
if (argc != 1) fatal("newStream: Expected 1 argument, got %d\n", argc);
oop arg = _get(args, Object, indexed)[0];
if (!is(String, arg)) fatal("newStream: expected an argument of type String, got type %s instead\n", getType(arg));
return newStream(arg);
}
oop prim_Stream_atEnd(oop func, oop self, oop args, oop env)
{
return newBoolean(_integerValue(Object_get(self, sym_position)) >= _integerValue(Object_get(self, sym_limit)));
}
oop prim_Stream_inc(oop func, oop self, oop args, oop env)
{
if (_integerValue(Object_get(self, sym_position)) < _integerValue(Object_get(self, sym_limit))) {
// There has to be a better way of just adding 1
Object_put(self, sym_position, newInteger(_integerValue(Object_get(self, sym_position)) + 1));
}
return Object_get(self, sym_position);
}
oop prim_Stream_setLastBegin(oop func, oop self, oop args, oop env)
{
return Object_put(self, sym_lastBegin, newInteger(_integerValue(Object_get(self, sym_position))));
}
oop prim_Stream_match(oop func, oop self, oop args, oop env)
{ assert(is(Object, args));
int argc = _get(args, Object,isize);
if (argc != 1) fatal("Stream.match: Expected 1 argument, got %d\n", argc);
oop arg = _get(args, Object, indexed)[0]; assert(is(String, arg));
return newBoolean(strncmp(
String_content(Object_get(self, sym_content)) + _integerValue(Object_get(self, sym_position)),
String_content(arg),
strlen(String_content(arg))
) == 0);
}
oop prim_length(oop func, oop self, oop args, oop env)
{ assert(is(Object, args));
if (!is(Object, self)) valueError("length", "not an object", self);
@ -4298,6 +4395,12 @@ oop prim_eval(oop func, oop self, oop args, oop env)
int argc = _get(args, Object,isize);
oop *indexed = _get(args, Object,indexed);
oop result = nil;
//if (nil != Object_getLocal(args, sym_env)) {
if (Object_find(args, sym_env) >= 0) {
env = Object_getLocal(args, sym_env);
}
for (int i = 0; i < argc; ++i) result = eval(indexed[i], env);
return result;
}
@ -4307,6 +4410,22 @@ oop prim___eval__(oop func, oop self, oop args, oop env)
return self;
}
oop prim_intern(oop func, oop self, oop args, oop env)
{
int argc = _get(args, Object,isize);
oop *indexed = _get(args, Object,indexed);
oop result = nil;
if (argc != 1) {
fatal("intern: invalid number of arguments");
}
if (getType(indexed[0]) != String) {
fatal("intern: argument is not of type String, got %s instead", getTypeName(indexed[0]));
}
return intern(String_content(indexed[0]));
}
oop prim_print(oop func, oop self, oop args, oop env)
{
int argc = _get(args, Object,isize);
@ -4797,7 +4916,7 @@ typedef struct vmState
oop variables;
} vmState;
#define VM_STATE_INITIALISER { nil, nil }
#define VM_STATE_INITIALISER { nil, new(pObject) }
void vmEnter(vmState *state, oop obj, char *yytext, int yyleng)
{
@ -4812,7 +4931,7 @@ void vmSet(vmState *state, oop obj, char *yytext, int yyleng)
void vmAction(vmState *state, oop obj, char *yytext, int yyleng)
{
oop text = yyleng ? newStringLen(yytext, yyleng) : nil;
oop text = yyleng >= 0 ? newStringLen(yytext, yyleng) : nil;
Object_put(state->variables, sym_yytext, text);
Object_put(state->variables, sym_yyleng, newInteger(yyleng));
applyThunkIn(obj, state->variables);
@ -4822,6 +4941,7 @@ void vmLeave(vmState *state, oop obj, char *yytext, int yyleng)
{
state->result = Object_getLocal(state->variables, sym_$$);
state->variables = _getDelegate(state->variables);
Object_put(state->variables, sym_$$, state->result);
}
void vmDisassemble(vmInsn *code, int pc)
@ -5019,6 +5139,8 @@ int vmRun(oop grammar0, oop symbol, char *text, int start, int length)
C##stack[--C##sp]; \
})
saveAction(vmEnter, nil, 0, 0);
for (;;) {
if (opt_d) vmDisassemble(frame.code, frame.pc);
vmInsn *i = frame.code + frame.pc++;
@ -5167,8 +5289,6 @@ int vmRun(oop grammar0, oop symbol, char *text, int start, int length)
break;
}
saveAction(vmLeave, nil, 0, 0);
#undef pop
#undef drop
#undef push
@ -5205,6 +5325,20 @@ oop prim_match(oop func, oop self, oop args, oop env)
#endif // PEGVM
oop prim_lvalue(oop func, oop self, oop args, oop env)
{ assert(is(Object, args));
int argc = _get(args, Object,isize);
if (argc != 1) fatal("lvalue: one argument expected\n");
return lvalue(_get(args, Object,indexed)[0]);
}
oop prim_assign(oop func, oop self, oop args, oop env)
{ assert(is(Object, args));
int argc = _get(args, Object,isize);
if (argc != 2) fatal("assign: 2 arguments expected\n");
return assign(_get(args, Object,indexed)[0], _get(args, Object,indexed)[1]);
}
oop replFile(FILE *in)
{
int oldline = lineno;
@ -5330,6 +5464,18 @@ int main(int argc, char **argv)
Object_put(pObject, prop_eval, newPrimitive(prim___eval__, newString("Object.__eval__"))); // inherited by all objects
#define stringify(x) #x
#define declareOp(NAME, OP) _set(intern(stringify(op##NAME)), Symbol,value, newInteger(op##NAME));
doBinops(declareOp)
#undef declareOp
#undef stringify
#define declareOp(NAME, OP) _set(intern(#NAME), Symbol,value, newInteger(NAME));
doUnyops(declareOp)
#undef declareOp
#if TYPECODES
# define defineEvaluator(NAME) \
@ -5375,6 +5521,12 @@ int main(int argc, char **argv)
prim(defined , prim_defined);
prim(__extern__ , prim_extern);
prim(__match__ , prim_match);
prim(intern , prim_intern);
prim(newBinop , prim_newBinop);
prim(newApply , prim_newApply);
prim(lvalue , prim_lvalue);
prim(assign , prim_assign);
prim(newStream , prim_newStream);
# undef prim
@ -5417,6 +5569,10 @@ int main(int argc, char **argv)
method(Symbol,define, prim_Symbol_define );
method(Symbol,value, prim_Symbol_value );
method(Symbol,allInstances, prim_Symbol_allInstances);
method(Stream,atEnd, prim_Stream_atEnd );
method(Stream,inc, prim_Stream_inc );
method(Stream,setLastBegin, prim_Stream_setLastBegin);
method(Stream,match, prim_Stream_match );
# undef method

+ 73
- 0
rawMetaGrammar.leg 파일 보기

@ -0,0 +1,73 @@
statement = b:block { b; }
| e:expression SEMI { e; }
expression = p:primary
( DOT i:id ASSIGN e:expression # { $$ = newSetProp(p, i, e) }
| LBRAK i:expression RBRAK ASSIGN e:expression { SetArray.new(object: p, index: i, value: e); }
)
| i:id ASSIGN e:expression { SetVar.new(name: i, value: e); }
| pf:postfix { pf; }
postfix = p:primary
( DOT i:id a:args !ASSIGN !LBRACE { p = Invoke.new(self: p, method: i, arguments: a); }
| DOT i:id !ASSIGN { p = GetProp.new(object: p, key: i); }
| a:args !ASSIGN !LBRACE { p = Call.new(function: p, arguments: a); }
) * { p; }
args = LPAREN a:mklist
(
( k:id COLON e:expression { a[k] = e; }
| e:expression { a.push(e); }
)
( COMMA
( k:id COLON e:expression { a[k] = e; }
| e:expression { a.push(e); }
)
) *
) ? RPAREN { a; }
mklist = { Object.new(); }
primary = nil | number | var | subExpr
subExpr = LPAREN e:expression RPAREN { e; }
block = LBRACE b:mklist
( e:statement { b.push(e); }
) * RBRACE { Block.new(body: b); }
nil = NIL { nil; }
number = "-" n:unsign { Unyop.new(operation: __opNeg).push(n) }
| "+" n:number { n }
| n:unsign { n }
unsign = < DIGIT+ > - { yytext.asInteger(10); }
var = i:id { GetVar.new(name: i); }
id = < LETTER ALNUM* > - { intern(yytext); }
DIGIT = [0-9]
LETTER = [A-Za-z_]
ALNUM = LETTER | DIGIT
NIL = "nil" !ALNUM -
SEMI = ";" -
COMMA = "," -
LPAREN = "(" -
RPAREN = ")" -
LBRAK = "[" -
RBRAK = "]" -
LBRACE = "{" -
RBRACE = "}" -
COLON = ":" ![:] -
ASSIGN = "=" ![=] -
DOT = "." ![.] -
- = ( space | comment )*
space = ' ' | '\t' | end-of-line
comment = '//' ( !end-of-line . )* end-of-line
end-of-line = '\r\n' | '\n' | '\r'
end-of-file = !.

+ 83
- 0
rawgrammar.leg 파일 보기

@ -0,0 +1,83 @@
grammar = - ( d:definition { global yysval = d; }
| end-of-file { global yysval = nil; }
)
definition = i:identifier ASSIGN e:expression SEMI? { $$ = Definition.new(name: i, expression: e); }
expression = s:sequence !BAR { $$ = s; }
| s1:sequence { s1 = Alternation.new().push(s1); }
( BAR s2:sequence { s1.push(s2); }
) * { $$ = s1; }
startSequence = - s:sequence { global yysval = s; }
sequence = p:prefix ( q:prefix { p = Sequence.new().push(p).push(q); }
( q:prefix { p.push(q); }
) * ) ? { $$ = p; }
prefix = AND a:action { $$ = ParseTimeAction.new(action: a); }
| AT a:action { $$ = ExecuteAction.new(action: a); }
|
( AND s:suffix { $$ = And.new(expression: s); }
| NOT s:suffix { $$ = Not.new(expression: s); }
| s:suffix { $$ = s; }
)
suffix = p:primary
( QUERY { p = Optional.new(expression: p); }
| STAR { p = Star.new(expression: p); }
| PLUS { p = Plus.new(expression: p); }
) ? { $$ = p; }
primary = i1:identifier COLON i2:ruleCall !ASSIGN { $$ = Assignment.new(name: i1, rule: i2); }
| i:ruleCall !ASSIGN { $$ = i; }
| LPAREN e:expression RPAREN { $$ = e; }
| l:literal { $$ = l; }
| c:class { $$ = c; }
| DOT { $$ = Dot.new(); }
| a:action { $$ = a; }
| BEGIN e:expression END { $$ = Capture.new(expression: e); }
identifier = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { $$ = intern(yytext); }
ruleCall = n:identifier CCOLON r:identifier { $$ = NamespacedRuleCall
.new(namespace: GetVar.new(name: n).__eval__(), name: r);
}
| i:identifier { $$ = RuleCall.new(name: i); }
literal = ['] < ( !['] char )* > ['] - { $$ = StringLiteral.new(string: yytext.unescaped()); }
| ["] < ( !["] char )* > ["] - { $$ = StringLiteral.new(string: yytext.unescaped()); }
class = '[' < ( !']' range )* > ']' - { $$ = CharacterClass.new(value: yytext.unescaped()); }
range = char '-' char | char
char = '\\' [abefnrtv'"\[\]\\]
| '\\' [0-3][0-7][0-7]
| '\\' [0-7][0-7]?
| !'\\' .
action = m:metaGrammar::block - { $$ = Action.new(parseTree: Block.new(body: m)); }
- = ( space | comment )*
space = ' ' | '\t' | end-of-line
comment = '#' ( !end-of-line . )* end-of-line
end-of-line = '\r\n' | '\n' | '\r'
end-of-file = !.
BAR = '|' -
NOT = '!' -
QUERY = '?' -
BEGIN = '<' -
END = '>' -
SEMI = ";" -
CCOLON = "::" -
LPAREN = "(" -
RPAREN = ")" -
ASSIGN = "=" ![=] -
AND = "&" ![&=] -
PLUS = "+" ![+=] -
STAR = "*" ![=] -
DOT = "." ![.] -
COLON = ":" ![:] -
AT = "@" -

+ 275
- 0
rawminproto.leg 파일 보기

@ -0,0 +1,275 @@
start = - ( s:stmt { s; }
| !. # { yysval = 0 }
| < (!EOL .)* > # { fatal("syntax error near: %s", yytext) }
)
stmt = WHILE LPAREN c:expr RPAREN s:stmt { While.new(condition: c, body: s) }
| IF LPAREN c:expr RPAREN s:stmt
( ELSE t:stmt { If.new(condition: c, consequent: s, alternate: t ) }
| { If.new(condition: c, consequent: s, alternate: nil) }
)
| CONT EOS { Continue.new() }
| BREAK e:expr EOS { Break.new(value: e) }
| BREAK EOS { Break.new(value: nil) }
| RETURN e:expr EOS { Return.new(value: e) }
| RETURN EOS { Return.new(value: nil) }
| FOR LPAREN i:id IN e:expr RPAREN
s:stmt { ForIn.new(identifier: i, expression: e, body: s) }
| FOR LPAREN i:id FROM a:expr
TO b:expr RPAREN s:stmt { ForFromTo.new(identifier: i, first: a, last: b, body: s) }
| FOR LPAREN i:expr SEMI c:expr SEMI
u:expr RPAREN s:stmt { For.new(initialise: i, condition: c, update: u, body: s) }
| TRY t:stmt
( CATCH LPAREN i:id RPAREN c:stmt { TryCatch.new(statement: t, identifier: i, handler: c) }
| ENSURE e:stmt { TryEnsure.new(statement: t, handler: e) }
)
| RAISE e:expr EOS { Raise.new(value: e) }
| LOCAL i:id p:params b:block { SetLocal.new(name: i, value: Lambda.new(parameters: p, body: b)) }
| GLOBAL i:id p:params b:block { SetGlobal.new(name: i, value: Lambda.new(parameters: p, body: b)) }
| i:id p:params b:block { SetVar.new(name: i, value: Lambda.new(parameters: p, body: b)) }
| v:proto DOT i:id p:params b:block { SetProp.new(object: v, key: i, value: Lambda.new(parameters: p, body: b)) }
| b:block { Block.new(body: b) }
| e:expr EOS { e }
proto = v:var ( DOT j:id !LPAREN { v = GetProp.new(object: v, key: j) }
)* { v }
EOS = SEMI+ | &RBRACE | &ELSE | &CATCH
expr = LOCAL i:id ASSIGN e:expr { SetLocal.new(name: i, value: e) }
| GLOBAL i:id ASSIGN e:expr { SetGlobal.new(name: i, value: e) }
| i:id ASSIGN e:expr { SetVar.new(name: i, value: e) }
| l:logor ( ASSIGN r:expr { l = assign(l, r) }
| PLUSEQ r:expr { l = newBinop(__opPreAdd, lvalue(l), r) }
| MINUSEQ r:expr { l = newBinop(__opPreSub, lvalue(l), r) }
| STAREQ r:expr { l = newBinop(__opPreMul, lvalue(l), r) }
| SLASHEQ r:expr { l = newBinop(__opPreDiv, lvalue(l), r) }
| PCENTEQ r:expr { l = newBinop(__opPreMod, lvalue(l), r) }
| SHLEQ r:expr { l = newBinop(__opPreShl, lvalue(l), r) }
| SHREQ r:expr { l = newBinop(__opPreShr, lvalue(l), r) }
| ANDEQ r:expr { l = newBinop(__opPreAnd, lvalue(l), r) }
| XOREQ r:expr { l = newBinop(__opPreXor, lvalue(l), r) }
| OREQ r:expr { l = newBinop(__opPreOr, lvalue(l), r) }
)? { l }
logor = l:logand ( BARBAR r:logand { l = newBinop(__opLogOr, l, r) }
)* { l }
logand = l:bitor ( ANDAND r:bitor { l = newBinop(__opLogAnd, l, r) }
)* { l }
bitor = l:bitxor ( OR r:bitxor { l = newBinop(__opBitOr, l, r) }
)* { l }
bitxor = l:bitand ( XOR r:bitand { l = newBinop(__opBitXor, l, r) }
)* { l }
bitand = l:eq ( AND r:eq { l = newBinop(__opBitAnd, l, r) }
)* { l }
eq = l:ineq ( EQ r:ineq { l = newBinop(__opEq, l, r) }
| NOTEQ r:ineq { l = newBinop(__opNotEq, l, r) }
)* { l }
ineq = l:shift ( LESS r:shift { l = newBinop(__opLess, l, r) }
| LESSEQ r:shift { l = newBinop(__opLessEq, l, r) }
| GRTREQ r:shift { l = newBinop(__opGrtrEq, l, r) }
| GRTR r:shift { l = newBinop(__opGrtr, l, r) }
)* { l }
shift = l:sum ( SHL r:sum { l = newBinop(__opShl, l, r) }
| SHR r:sum { l = newBinop(__opShr, l, r) }
)* { l }
sum = l:prod ( PLUS r:prod { l = newBinop(__opAdd, l, r) }
| MINUS r:prod { l = newBinop(__opSub, l, r) }
)* { l }
prod = l:range ( STAR r:range { l = newBinop(__opMul, l, r) }
| SLASH r:range { l = newBinop(__opDiv, l, r) }
| PCENT r:range { l = newBinop(__opMod, l, r) }
) * { l }
range = i1:prefix ( DOTDOT i2:prefix { i1 = Range.new(start: i1, end: i2) }
) ? { i1 }
prefix = PPLUS p:prefix { newBinop(__opPreAdd, lvalue(p), 1) }
| MMINUS p:prefix { newBinop(__opPreSub, lvalue(p), 1) }
| PLING p:prefix { Unyop.new(operation: __opNot).push(p) }
| MINUS p:prefix { Unyop.new(operation: __opNeg).push(p) }
| TILDE p:prefix { Unyop.new(operation: __opCom).push(p) }
| BQUOTE s:stmt { Unyop.new(operation: __opQuasiquote).push(s) }
| COMMAT e:expr { Unyop.new(operation: __opUnquote).push(e) }
| postfix
postfix = SUPER DOT i:id a:args { Super.new(method: i, arguments: a) }
| p:primary
( LBRAK e:expr RBRAK { p = GetArray.new(object: p, index: e) }
| DOT i:id ( a:args !LBRACE { p = Invoke.new(self: p, method: i, arguments: a) }
| { p = GetProp.new(object: p, key: i) }
)
| a:args !LBRACE { p = newApply(p, a) }
)*
( PPLUS { p = newBinop(__opPostAdd, lvalue(p), 1) }
| MMINUS { p = newBinop(__opPostAdd, lvalue(p), -1) }
)? { p }
args = LPAREN a:mkobj
( RPAREN
| ( k:id COLON e:expr { a[k] = e }
| e:expr { a.push(e) }
)
( COMMA ( k:id COLON e:expr { a[k] = e }
| e:expr { a.push(e) }
) )* RPAREN ) { a }
params = LPAREN p:mkobj
( RPAREN
| i:id ( COLON e:expr { p[i] = e }
| { p.push(i) }
)
( COMMA i:id ( COLON e:expr { p[i] = e }
| { p.push(i) }
)
)* RPAREN ) { p }
mkobj = { Object.new() }
primary = nil | number | string | symbol | var | lambda | subexpr | literal
lambda = p:params b:block { Lambda.new(parameters: p, body: b) }
subexpr = LPAREN e:expr RPAREN { e }
| b:block { Block.new(body: b) }
literal = LBRAK o:mkobj
( RBRAK
| ( ( i:id COLON e:expr { o[i] = e }
| e:expr { o.push(e) }
) ( COMMA ( i:id COLON e:expr { o[i] = e }
| e:expr { o.push(e) }
) )* )? RBRAK ) { Literal.new(object: o) }
block = LBRACE b:mkobj
( e:stmt { b.push(e) }
)* RBRACE { b }
nil = NIL { nil }
number = "-" n:unsign { Unyop.new(operation: __opNeg).push(n) }
| "+" n:number { n }
| n:unsign { n }
unsign = < DIGIT* '.' DIGIT+ EXP? > - { yytext.asFloat() }
| "0" [bB] < BIGIT+ > - { yytext.asInteger(2) }
| "0" [xX] < HIGIT+ > - { yytext.asInteger(16) }
| "0" < OIGIT* > - { yytext.asInteger(8) }
| < DIGIT+ > - { yytext.asInteger() }
| "'" < char > "'" - { ord(yytext.unescaped()) }
string = '"' < ( !'"' char )* > '"' - { yytext }
# Version originale, qui ne parse pas deux antislash pour une raison obscure
# char = "\\" ( ["'\\abfnrtv]
# | [xX] HIGIT*
# | [0-7][0-7]?[0-7]?
# )
# | .
# Version de rawgrammar.leg, qui fonctionne sans problème
char = '\\' [abefnrtv'"\[\]\\]
| '\\' [0-3][0-7][0-7]
| '\\' [0-7][0-7]?
| '\\' [xX] HIGIT+
| !'\\' .
symbol = HASH i:id { i }
var = LOCAL i:id { GetLocal.new(name: i) }
| GLOBAL i:id { GetGlobal.new(name: i) }
| i:id { GetVar.new(name: i) }
id = < LETTER ALNUM* > - { intern(yytext) }
BIGIT = [0-1]
OIGIT = [0-7]
DIGIT = [0-9]
HIGIT = [0-9A-Fa-f]
LETTER = [A-Za-z_$?]
ALNUM = LETTER | DIGIT
SIGN = [-+]
EXP = [eE] SIGN DIGIT+
- = SPACE*
SPACE = [ \t] | EOL | SLC | MLC
EOL = [\n\r] # { ++lineno }
SLC = "//" (!EOL .)*
MLC = "/*" ( MLC | !"*/" (EOL | .))* "*/" -
NIL = "nil" !ALNUM -
WHILE = "while" !ALNUM -
IF = "if" !ALNUM -
ELSE = "else" !ALNUM -
FOR = "for" !ALNUM -
IN = "in" !ALNUM -
FROM = "from" !ALNUM -
TO = "to" !ALNUM -
CONT = "continue" !ALNUM -
BREAK = "break" !ALNUM -
RETURN = "return" !ALNUM -
TRY = "try" !ALNUM -
CATCH = "catch" !ALNUM -
ENSURE = "ensure" !ALNUM -
RAISE = "raise" !ALNUM -
GLOBAL = "global" !ALNUM -
LOCAL = "local" !ALNUM -
SUPER = "super" !ALNUM -
BQUOTE = "`" -
COMMAT = "@" -
HASH = "#" -
SEMI = ";" -
ASSIGN = "=" ![=] -
COMMA = "," -
COLON = ":" ![:] -
LPAREN = "(" -
RPAREN = ")" -
LBRAK = "[" -
RBRAK = "]" -
LBRACE = "{" -
RBRACE = "}" -
BARBAR = "||" ![=] -
ANDAND = "&&" ![=] -
OR = "|" ![|=] -
OREQ = "|=" -
XOR = "^" ![=] -
XOREQ = "^=" -
AND = "&" ![&=] -
ANDEQ = "&=" -
EQ = "==" -
NOTEQ = "!=" -
LESS = "<" ![<=] -
LESSEQ = "<=" -
GRTREQ = ">=" -
GRTR = ">" ![=] -
SHL = "<<" ![=] -
SHLEQ = "<<=" -
SHR = ">>" ![=] -
SHREQ = ">>=" -
PLUS = "+" ![+=] -
PLUSEQ = "+=" -
PPLUS = "++" -
MINUS = "-" ![-=] -
MINUSEQ = "-=" -
MMINUS = "--" -
STAR = "*" ![=] -
STAREQ = "*=" -
SLASH = "/" ![/=] -
SLASHEQ = "/=" -
PCENT = "%" ![=] -
PCENTEQ = "%=" -
DOT = "." ![.] -
DOTDOT = ".." -
PLING = "!" ![=] -
TILDE = "~" -

+ 6
- 0
test.txt 파일 보기

@ -378,6 +378,12 @@ ast = (`6 * @myNode;); // user-defined node in AST
print("AST eval => ", eval(ast), "\n");
print("String to int conversion\n");
print("11111111".asInteger(2), "\n");
print("377".asInteger(8), "\n");
print("255".asInteger(), "\n");
print("FF".asInteger(16), "\n");
for (i from 0 to 10) print(i, " "); print("\n");
for (i from 10 to 0) print(i, " "); print("\n");
for (i in 10) print(i, " "); print("\n");

불러오는 중...
취소
저장