26 Commits

Auteur SHA1 Bericht Datum
  MaximeBarniaudy 827915384b 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. 1 jaar geleden
  MaximeBarniaudy 43c178c6ac Move side effect of variable assignment in namespace out of grammar for logic and ease of use reasons 1 jaar geleden
  MaximeBarniaudy 81bf3791d9 Remove old unused code, and measure parsing speed 1 jaar geleden
  MaximeBarniaudy 8b62b9cb50 Use newest primitives for character class and string matching 1 jaar geleden
  MaximeBarniaudy e7ecaff9b8 Build Grammar objects whose methods are expression representations of grammar rules 1 jaar geleden
  MaximeBarniaudy 733a5d8a86 Fix errors after SetVar behavior change and let removal 1 jaar geleden
  MaximeBarniaudy 2e56f8e799 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. 1 jaar geleden
  MaximeBarniaudy 1afbb06f1c Make grammar_parser.meta use the entire grammar from minproto.leg 1 jaar geleden
  MaximeBarniaudy 408ee602ca Add optional base argument to String.asInteger 1 jaar geleden
  MaximeBarniaudy 394e83f392 Fix error after single quote semantics change 1 jaar geleden
  MaximeBarniaudy e7c5ef13f7 Add with and without functions for namespace manimulation, add namespace support to grammars, add test of parser circularity 1 jaar geleden
  MaximeBarniaudy 591a5c67f8 parser circularity 1 jaar geleden
  MaximeBarniaudy d474e03e5d dotdot got lost in merging 1 jaar geleden
  MaximeBarniaudy 2fc5795107 Add Invoke and GetProp 1 jaar geleden
  MaximeBarniaudy 953fcb3c9d Minimal grammar parsing 1 jaar geleden
  MaximeBarniaudy 5324c1dc77 Add an intern primitive for symbol creation 1 jaar geleden
  WitherFlower 6300436ba2 Merge range access and grammar parser changes 1 jaar geleden
  Ian Piumarta 436f2caa76 String_append(), _appendAll(), and _format() allocate new memory to allow raw pointers to old content to persist. Add PEG operations TEST (fail if function returns false) and RULE2 (call rule in other grammar). PEG instruction's second operand is object not integer. Initialise top level state.variables with empty object in vmRun(). PEG instruction FAIL removes all actions added by its rule. 1 jaar geleden
  Ian Piumarta 1f030c7ae4 Turn off bogus compiler warnings about bounds errors when optimising. 1 jaar geleden
  Ian Piumarta 7e46198826 Fix double-eval bug in apply(). Grow buffers by more than 1 wherever performance matters. 1 jaar geleden
  Ian Piumarta ea38861c4d vmCompile() checks that all PC destinations are in range. STRING and CLASS opcodes read the argument length from their string, ignoring the explicit length given in the program. 1 jaar geleden
  Ian Piumarta 1ea2557f7e Fix digitValue() and reading of numerical escaped characters in strings. Indexing a string always returns an unsigned char value. Add PEG VM and corresponding primitive __match__(). 1 jaar geleden
  Ian Piumarta c10c320d4e Add profiling support when compiled with PROFILE=1 and command-line option -p to enable profiling. Add [from:to] syntax for array and string slices. Fix passing of environment between primitive and user-defined __eval__ methods. 1 jaar geleden
  Ian Piumarta 6ae2155b92 Remove let keyword in front of local definition. 1 jaar geleden
  Ian Piumarta d6a9d2e88f Remove let keyword in front of local definition. 1 jaar geleden
  Ian Piumarta 2e94543651 Enable profiling when poducing release binary. 1 jaar geleden
10 gewijzigde bestanden met toevoegingen van 3446 en 116 verwijderingen
  1. +7
    -4
      Makefile
  2. +2
    -2
      bench-sieve.txt
  3. +1688
    -0
      grammar_parser.meta
  4. +316
    -0
      minproto.grammar
  5. +999
    -109
      minproto.leg
  6. +1
    -1
      profile-generate.txt
  7. +73
    -0
      rawMetaGrammar.leg
  8. +79
    -0
      rawgrammar.leg
  9. +275
    -0
      rawminproto.leg
  10. +6
    -0
      test.txt

+ 7
- 4
Makefile Bestand weergeven

@ -5,7 +5,7 @@ ifeq ($(UNAME_S),Darwin)
endif
GFLAGS += -Wall -Wno-unused -g
OFLAGS += $(GFLAGS) -O3 -DNDEBUG -DTYPECODES=1 -DDELOPT=1
OFLAGS += $(GFLAGS) -O3 -DNDEBUG -DTYPECODES=1 -DDELOPT=1 -Wno-array-bounds
PFLAGS += $(OFLAGS) -pg
CFLAGS += -D_GNU_SOURCE -I/opt/local/include
LDLIBS += -L/opt/local/lib
@ -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
@ -58,9 +61,9 @@ profile : $(MAIN)-prof
release : .FORCE
rm -f *.gcda
$(MAKE) clean all GFLAGS="-DNDEBUG -DTYPECODES=1 -DDELOPT=1 -O3 -fprofile-correction -fprofile-generate"
$(MAKE) clean all GFLAGS="-DNDEBUG -DTYPECODES=1 -DDELOPT=1 -DPROFILE=1 -O3 -fprofile-correction -fprofile-generate"
./$(MAIN) -O profile-generate.txt profile-generate.txt profile-generate.txt profile-generate.txt
$(MAKE) clean all GFLAGS="-DNDEBUG -DTYPECODES=1 -DDELOPT=1 -O3 -fprofile-correction -fprofile-use"
$(MAKE) clean all GFLAGS="-DNDEBUG -DTYPECODES=1 -DDELOPT=1 -DPROFILE=1 -O3 -fprofile-correction -fprofile-use"
./$(MAIN) -O profile-generate.txt
FILES = Makefile $(MAIN).leg bench.txt test.txt test2.txt

+ 2
- 2
bench-sieve.txt Bestand weergeven

@ -3,7 +3,7 @@
// 178589010 nodes evaluated in 2.126711 seconds = 83974273 nodes/sec
numbers = 8192; // 1028 primes
repeats = 200;
repeats = 10; // 200;
count = 0;
@ -13,7 +13,7 @@ evals = evaluations();
for (n = 0; n < repeats; n = n + 1) {
print("\r", n, "/", repeats);
let sieve = [];
sieve = [];
count = 0;
for (i in numbers) sieve.push(nil);
for (i = 2; i < numbers; i = i + 1) {

+ 1688
- 0
grammar_parser.meta
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 316
- 0
minproto.grammar Bestand weergeven

@ -0,0 +1,316 @@
# minproto.leg -- minimal prototype langauge for semantic experiments
#
# last edited: 2024-07-04 10:07:00 by piumarta on zora
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) }

+ 999
- 109
minproto.leg
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 1
- 1
profile-generate.txt Bestand weergeven

@ -20,7 +20,7 @@ evals = evaluations();
for (n = 0; n < repeats; n = n + 1) {
print("\r", n, "/", repeats);
let sieve = [];
sieve = [];
count = 0;
for (i in numbers) sieve.push(nil);
for (i = 2; i < numbers; i = i + 1) {

+ 73
- 0
rawMetaGrammar.leg Bestand weergeven

@ -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 = !.

+ 79
- 0
rawgrammar.leg Bestand weergeven

@ -0,0 +1,79 @@
grammar = - ( d:definition { d; }
| end-of-file { 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; }
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: n, name: r); }
| i:identifier { RuleCall.new(name: i); }
literal = ['] < ( !['] char )* > ['] - { StringLiteral.new(string: yytext); }
| ["] < ( !["] char )* > ["] - { StringLiteral.new(string: yytext); }
class = '[' < ( !']' range )* > ']' - { CharacterClass.new(value: yytext); }
range = char '-' char | char
char = '\\' [abefnrtv'"\[\]\\]
| '\\' [0-3][0-7][0-7]
| '\\' [0-7][0-7]?
| !'\\' .
action = m:metaLanguage::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 Bestand weergeven

@ -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 Bestand weergeven

@ -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");

Laden…
Annuleren
Opslaan