10 Commits

Autor SHA1 Mensagem Data
  MaximeBarniaudy 76bc7c91dd parser circularity 1 ano atrás
  MaximeBarniaudy 9d278ae10d dotdot got lost in merging 1 ano atrás
  MaximeBarniaudy 393f937218 Add Invoke and GetProp 1 ano atrás
  MaximeBarniaudy 4e904d213a Minimal grammar parsing 1 ano atrás
  MaximeBarniaudy 9befc31bb3 Add an intern primitive for symbol creation 1 ano atrás
  MaximeBarniaudy f3a2b47be9 Fix range access overshadowing key access 1 ano atrás
  WitherFlower 5d11b521e5 Merge range access and grammar parser changes 1 ano atrás
  Ian Piumarta c5c29bdbb0 Add release target that uses profile guided optimisation. 1 ano atrás
  Ian Piumarta 5e59fa586e Restore original benchmark size and number of repeats. 1 ano atrás
  Ian Piumarta 4ac12f91c5 Add symbols #O, #d, #v and Symbol.setop() primitive. Add primitive method Symbol.setopt(N) to set command-line option at runtime. Add primitive method Symbol.defined() to test if a variable name has been defined. Overload primitive "+" to concatenate strings. Add stack of namespaces, initialised to empty object. refvar() and getvar() search namespaces, from most to least recent, when looking for global variables. setvar() always defines globals in the most recent namespace regardless of any existing shadowed definitions. Make OBJ::NAME a synonym for OBJ.NAME except that OBJ::NAME() applies a function whereas OBJ.NAME() invokes method NAME on OBJ. Add primitive error() to print source location, error message, and backtrace. 1 ano atrás
5 arquivos alterados com 1276 adições e 48 exclusões
Visão dividida
  1. +8
    -1
      Makefile
  2. +2
    -2
      bench-sieve.txt
  3. +948
    -0
      grammar_parser.meta
  4. +184
    -45
      minproto.leg
  5. +134
    -0
      rawgrammar.leg

+ 8
- 1
Makefile Ver arquivo

@ -1,5 +1,5 @@
OFLAGS += -Wall -Wno-unused -O3 -DNDEBUG
GFLAGS += -Wall -Wno-unused -g
OFLAGS += $(GFLAGS) -O3 -DNDEBUG
PFLAGS += $(OFLAGS) -pg
CFLAGS += -D_GNU_SOURCE -I/opt/local/include
LDLIBS += -L/opt/local/lib
@ -42,6 +42,13 @@ profile : $(MAIN)-prof
./$(MAIN)-prof -O < bench.txt
gprof ./$(MAIN)-prof gmon.out
release : .FORCE
rm -f *.gcda
$(MAKE) clean all GFLAGS="-DNDEBUG -DTYPECODES=1 -DDELOPT=1 -O3 -fprofile-correction -fprofile-generate"
./$(MAIN) 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"
./$(MAIN) profile-generate.txt
FILES = Makefile $(MAIN).leg bench.txt test.txt test2.txt
checkpoint : .FORCE

+ 2
- 2
bench-sieve.txt Ver arquivo

@ -2,8 +2,8 @@
// 178589010 nodes evaluated in 2.129754 seconds = 83854290 nodes/sec
// 178589010 nodes evaluated in 2.126711 seconds = 83974273 nodes/sec
numbers = 819200; // 1028 primes
repeats = 10;
numbers = 8192; // 1028 primes
repeats = 200;
count = 0;

+ 948
- 0
grammar_parser.meta Ver arquivo

@ -0,0 +1,948 @@
// Utils
println = (x) {
if (!x) {
print("\n");
} else {
print(x, "\n", full: 1);
}
};
Object.subtype(name) { self.new(__name__: name) }
// Input stream
Stream = Object.subtype(#Stream);
newStream(string) {
let self = Stream.new(
content: string,
position: 0,
limit: len(string)
);
self;
}
Stream.atEnd() { self.position >= self.limit }
Stream.peek() { !self.atEnd() && self.content[self.position] }
Stream.inc() { !self.atEnd() && { self.position = self.position + 1; } }
Stream.next() {
!self.atEnd() && {
let c = self.content[self.position];
self.position = self.position + 1;
c;
}
}
Stream.setLastBegin = () { self.lastBegin = self.position; };
// Context
Context = Object.subtype(#Context);
Context.init() { self.variables = []; self; }
Context.declareVariable(var) {
let found = 0;
for (key in self.variables.keys()) {
if (key == var) {
found = 1;
}
}
if (found == 0) {
self.variables[var] = nil;
}
}
// ----- Grammar Constructs -----
// String Literal
StringLiteral = Object.subtype(#StringLiteral);
StringLiteral.match(stream, context, rules, actions) {
let n = len(self.string);
let i = 0;
let success = 1;
if (stream.atEnd()) { success = 0; }
startPosition = stream.position;
while(i < n && success == 1) {
if (self.string[i] != stream.peek()) {
success = 0;
stream.position = startPosition;
} else {
i = i + 1;
stream.inc();
}
}
success;
}
// Character Class
CharacterClass = Object.subtype(#CharacterClass);
CharacterClass.match(stream, context, rules, actions) {
let classLength = len(self.value);
let i = 0;
let prevChar = nil;
let success = 0;
while (i < classLength && success == 0 && !stream.atEnd()) {
// [a] case
if (prevChar == nil) {
// println("[a] case");
prevChar = self.value[i];
if (stream.peek() == self.value[i]) {
success = 1;
}
} else if (prevChar != nil && self.value[i] == ord('-')) {
// [a-z] case
if (i+1 < classLength) {
// println("[a-z] case");
rangeStart = prevChar;
rangeEnd = self.value[i+1];
// print("Range Start: ", rangeStart, " | ");
// print("Range End: ", rangeEnd, "\n");
if (stream.peek() >= rangeStart
&& stream.peek() <= rangeEnd
) {
success = 1;
}
prevChar = nil;
i = i + 1;
// [a-] case
} else {
// println("[a-] case");
if (stream.peek() == ord('-')) {
success = 1;
}
}
// [ab] case
} else if (prevChar != nil && self.value[i] != ord('-')) {
// println("[ab] case");
prevChar = self.value[i];
if (stream.peek() == self.value[i]) {
success = 1;
}
}
// print("prevChar: ", prevChar, "\n");
i = i + 1;
}
if (success == 1) {
stream.inc();
}
success;
}
// Dot
Dot = Object.subtype(#Dot);
Dot.match(stream, context, rules, actions) {
if (!stream.atEnd()) {
stream.inc();
1;
} else {
0;
}
}
// Begin
Begin = Object.subtype(#Begin);
Begin.match(stream, context, rules, actions) {
stream.setLastBegin();
1;
}
// End
End = Object.subtype(#End);
End.match(stream, context, rules, actions) {
context.variables.yytext = escapeString(stream.content[stream.lastBegin..stream.position]);
1;
}
// Optional (? postfix operator)
Optional = Object.subtype(#Optional);
Optional.match(stream, context, rules, actions) {
let initialActionCount = actions.length();
let startingPosition = stream.position;
let success = self.expression.match(stream, context, rules, actions);
if (success == 0) {
while (actions.length() > initialActionCount) {
actions.pop();
}
stream.position = startingPosition;
}
1;
}
// Star
Star = Object.subtype(#Star);
Star.match(stream, context, rules, actions) {
while (self.expression.match(stream, context, rules, actions) == 1) {}
1;
}
// Plus
Plus = Object.subtype(#Plus);
Plus.match(stream, context, rules, actions) {
if (self.expression.match(stream, context, rules, actions) == 1) {
while (self.expression.match(stream, context, rules, actions) == 1) {}
1;
} else {
0;
}
}
// And
And = Object.subtype(#And);
And.match(stream, context, rules, actions) {
let position = stream.position;
if (self.expression.match(stream, context, rules, actions) == 1) {
stream.position = position;
1;
} else {
0;
}
}
// Not
Not = Object.subtype(#Not);
Not.match(stream, context, rules, actions) {
let position = stream.position;
if (self.expression.match(stream, context, rules, actions) == 1) {
stream.position = position;
0;
} else {
1;
}
}
// Sequence
Sequence = Object.subtype(#Sequence);
Sequence.match(stream, context, rules, actions) {
let i = 0;
let match = 1;
while (i < self.length() && match == 1) {
match = self[i].match(stream, context, rules, actions);
i = i + 1;
}
match;
}
// Alternation
Alternation = Object.subtype(#Alternation);
Alternation.match(stream, context, rules, actions) {
let i = 0;
let success = 0;
while (i < self.length() && success == 0) {
let initialActionCount = actions.length();
let startingPosition = stream.position;
success = self[i].match(stream, context, rules, actions);
if (success == 0) {
while (actions.length() > initialActionCount) {
actions.pop();
}
stream.position = startingPosition;
}
i = i + 1;
}
success;
}
// Action
Action = Object.subtype(#Action);
Action.match(stream, context, rules, actions) {
actions.push([action: self, context: context]);
1;
}
Action.execute(context) {
// Declare all variables that a value is set to in the context
for (statement in self.parseTree.body) {
if (statement.__name__ == "SetVar") {
context.declareVariable(statement.name);
}
}
// Evaluate the parse tree and return to outer context if needed
returnValue = eval(self.parseTree, env: context.variables);
if (context.outerContext != nil) {
context.outerContext.variables[context.returnValueName] = returnValue;
}
returnValue;
}
// Parse-time Action
ParseTimeAction = Object.subtype(#ParseTimeAction);
ParseTimeAction.match(stream, context, rules, actions) {
if(self.action.execute(context)) {
1;
} else {
0;
}
}
// Assignment
Assignment = Object.subtype(#Assignment);
Assignment.match(stream, context, rules, actions) {
context.declareVariable(self.name);
innerContext = Context.new(outerContext: context, returnValueName: self.name).init();
self.rule.match(stream, innerContext, rules, actions);
}
// RuleCall
RuleCall = Object.subtype(#RuleCall);
RuleCall.match(stream, context, rules, actions) {
if (rules[self.name] == nil) { print("Trying to call undefined rule: ", self.name, "\n"); exit(); }
rules[self.name].match(stream, context, rules, actions);
}
// ----- Grammar of Grammars -----
rules = [];
// grammar = - g:mklist
// ( d:definition { g.push(d); }
// ) + end-of-file { print(g, full: Object.new()); }
rules.grammar = Sequence.new()
.push(RuleCall.new(name: #ws))
.push(Assignment.new(name: #g, rule: RuleCall.new(name: #mklist)))
.push(Plus.new(expression: Sequence.new()
.push(Assignment.new(name: #d, rule: RuleCall.new(name: #definition)))
.push(Action.new(parseTree: `{ g[d.name] = d.expression; }))
))
.push(RuleCall.new(name: #end_of_file))
.push(Action.new(parseTree: `{ g; }));
Definition = Object.subtype(#Definition);
// definition = i:identifier ASSIGN e:expression SEMI? { newDefinition(i, e); }
rules.definition = Sequence.new()
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #identifier)))
.push(RuleCall.new(name: #assign))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #expression)))
.push(Optional.new(expression: RuleCall.new(name: #semi)))
.push(Action.new(parseTree: `{ Definition.new(name: i, expression: e); }));
// expression = s1:sequence ( BAR s2:sequence { s1 = newAlternation(s1, s2); }
// ) * { s1; }
rules.expression = Sequence.new()
.push(Assignment.new(name: #s1, rule: RuleCall.new(name: #sequence)))
.push(Action.new(parseTree: `{ s1 = Alternation.new().push(s1); }))
.push(Star.new(expression: Sequence.new()
.push(RuleCall.new(name: #bar))
.push(Assignment.new(name: #s2, rule: RuleCall.new(name: #sequence)))
.push(Action.new(parseTree: `{ s1.push(s2); }))
))
.push(Action.new(parseTree: `{ s1; }));
// sequence = p:prefix
// ( q:prefix { p = newSequence(p, q); }
// ) * { p; }
rules.sequence = Sequence.new()
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #prefix)))
.push(Action.new(parseTree: `{ p = Sequence.new().push(p); }))
.push(Star.new(expression: Sequence.new()
.push(Assignment.new(name: #q, rule: RuleCall.new(name: #prefix)))
.push(Action.new(parseTree: `{ p.push(q); }))
))
.push(Action.new(parseTree: `{ p; }));
// prefix = AND action
// |
// ( AND s:suffix { newAnd(s); }
// | NOT s:suffix { newNot(s); }
// | s:suffix { s; }
// )
rules.prefix = Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #and))
.push(RuleCall.new(name: #action))
)
.push(Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #and))
.push(Assignment.new(name: #s, rule: RuleCall.new(name: #suffix)))
.push(Action.new(parseTree: `{ And.new(expression: s); }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #not))
.push(Assignment.new(name: #s, rule: RuleCall.new(name: #suffix)))
.push(Action.new(parseTree: `{ Not.new(expression: s); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #s, rule: RuleCall.new(name: #suffix)))
.push(Action.new(parseTree: `{ s; }))
)
);
// suffix = p:primary
// ( QUERY { p = newOptional(p); }
// | STAR { p = newStar(p); }
// | PLUS { p = newPlus(p); }
// ) ? { p; }
rules.suffix = Sequence.new()
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #primary)))
.push(Optional.new(expression: Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #query))
.push(Action.new(parseTree: `{ p = Optional.new(expression: p); }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #star))
.push(Action.new(parseTree: `{ p = Star.new(expression: p); }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #plus))
.push(Action.new(parseTree: `{ p = Plus.new(expression: p); }))
)
))
.push(Action.new(parseTree: `{ p; }));
// primary = i1:identifier COLON i2:ruleCallIdent !ASSIGN { newAssignment(i1, i2); }
// | i:ruleCallIdent !ASSIGN { i; }
// | LPAREN e:expression RPAREN { e; }
// | l:literal { l; }
// | c:class { c; }
// | DOT { newDot(); }
// | a:action { a; }
// | BEGIN { newBegin(); }
// | END { newEnd(); }
rules.primary = Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #i1, rule: RuleCall.new(name: #identifier)))
.push(RuleCall.new(name: #colon))
.push(Assignment.new(name: #i2, rule: RuleCall.new(name: #ruleCallIdent)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Action.new(parseTree: `{ Assignment.new(name: i1, rule: i2); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #ruleCallIdent)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Action.new(parseTree: `{ i; }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #lparen))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #expression)))
.push(RuleCall.new(name: #rparen))
.push(Action.new(parseTree: `{ e; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #l, rule: RuleCall.new(name: #literal)))
.push(Action.new(parseTree: `{ l; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #c, rule: RuleCall.new(name: #class)))
.push(Action.new(parseTree: `{ c; }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #dot))
.push(Action.new(parseTree: `{ Dot.new(); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #a, rule: RuleCall.new(name: #action)))
.push(Action.new(parseTree: `{ a; }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #begin))
.push(Action.new(parseTree: `{ Begin.new(); }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #end))
.push(Action.new(parseTree: `{ End.new(); }))
);
// identifier = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { newStringEscaped(yytext); }
rules.identifier = Sequence.new()
.push(Begin.new())
.push(CharacterClass.new(value: "-a-zA-Z_"))
.push(Star.new(expression: CharacterClass.new(value: "-a-zA-Z_0-9")))
.push(End.new())
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ intern(yytext); }));
// ruleCallIdent = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { newIdentifier(yytext); }
rules.ruleCallIdent = Sequence.new()
.push(Begin.new())
.push(CharacterClass.new(value: "-a-zA-Z_"))
.push(Star.new(expression: CharacterClass.new(value: "-a-zA-Z_0-9")))
.push(End.new())
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ RuleCall.new(name: intern(yytext)); }));
// literal = ['] < ( !['] char )* > ['] - { newStringEscaped(yytext); }
// | ["] < ( !["] char )* > ["] - { newStringEscaped(yytext); }
rules.literal = Alternation.new()
.push(Sequence.new()
.push(CharacterClass.new(value: "\'"))
.push(Begin.new())
.push(Star.new(expression: Sequence.new()
.push(Not.new(expression: CharacterClass.new(value: "\'")))
.push(RuleCall.new(name: #char))
))
.push(End.new())
.push(CharacterClass.new(value: "\'"))
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ StringLiteral.new(string: yytext); }))
)
.push(Sequence.new()
.push(CharacterClass.new(value: '\"'))
.push(Begin.new())
.push(Star.new(expression: Sequence.new()
.push(Not.new(expression: CharacterClass.new(value: '\"')))
.push(RuleCall.new(name: #char))
))
.push(End.new())
.push(CharacterClass.new(value: '\"'))
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ StringLiteral.new(string: yytext); }))
);
// class = '[' < ( !']' range )* > ']' - { newCharacterClass(yytext); }
rules.class = Sequence.new()
.push(StringLiteral.new(string: "["))
.push(Begin.new())
.push(Star.new(expression: Sequence.new()
.push(Not.new(expression: StringLiteral.new(string: "]")))
.push(RuleCall.new(name: #range))
))
.push(End.new())
.push(StringLiteral.new(string: "]"))
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ CharacterClass.new(value: yytext); }));
// range = char '-' char | char
rules.range = Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #char))
.push(StringLiteral.new(string: "-"))
.push(RuleCall.new(name: #char))
)
.push(
RuleCall.new(name: #char)
);
// char = '\\' [abefnrtv'"\[\]\\]
// | '\\' [0-3][0-7][0-7]
// | '\\' [0-7][0-7]?
// | !'\\' .
rules.char = Alternation.new()
.push(Sequence.new()
.push(StringLiteral.new(string: "\\"))
.push(CharacterClass.new(value: "abefnrtv\'\"[]\\"))
)
.push(Sequence.new()
.push(StringLiteral.new(string: "\\"))
.push(CharacterClass.new(value: "0-3"))
.push(CharacterClass.new(value: "0-7"))
.push(CharacterClass.new(value: "0-7"))
)
.push(Sequence.new()
.push(StringLiteral.new(string: "\\"))
.push(CharacterClass.new(value: "0-7"))
.push(Optional.new(expression: CharacterClass.new(value: "0-7")))
)
.push(Sequence.new()
.push(Not.new(expression: StringLiteral.new(string: "\\")))
.push(Dot.new())
);
// action = m:metaBlock - { newAction(m); }
rules.action = Sequence.new()
.push(Assignment.new(name: #m, rule: RuleCall.new(name: #metaBlock)))
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ Action.new(parseTree: m); }));
// metaStatement = b:metaBlock { b; }
// | e:metaExpression SEMI { e; }
rules.metaStatement = Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #b, rule: RuleCall.new(name: #metaBlock)))
.push(Action.new(parseTree: `{ b; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(RuleCall.new(name: #semi))
.push(Action.new(parseTree: `{ e; }))
);
// metaExpression = p:metaPrimary
// ( DOT i:metaId ASSIGN e:metaExpression # { $$ = newSetProp(p, i, e) }
// | LBRAK i:metaExpression RBRAK ASSIGN e:metaExpression # { $$ = newSetArray(p, i, e) }
// )
// | i:metaId ASSIGN e:metaExpression { newSetVar(i, e); }
// | pf:metaPostfix { pf; }
rules.metaExpression = Alternation.new(id: 1234)
.push(Sequence.new()
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #metaPrimary)))
.push(Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #dot))
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(RuleCall.new(name: #assign))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
)
.push(Sequence.new()
.push(RuleCall.new(name: #lbrak))
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaExpression)))
.push(RuleCall.new(name: #rbrak))
.push(RuleCall.new(name: #assign))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ SetArray.new(object: p, index: i, value: e); }))
)
)
)
.push(Sequence.new()
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(RuleCall.new(name: #assign))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ SetVar.new(name: i, value: e); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #pf, rule: RuleCall.new(name: #metaPostfix)))
.push(Action.new(parseTree: `{ pf; }))
);
// metaPostfix = p:metaPrimary
// ( DOT i:id a:args !ASSIGN !LBRACE { p = newInvoke(p, i, a) }
// | DOT i:id !ASSIGN { p = newGetProp(p, i) }
// | a:args !ASSIGN !LBRACE { p = newCall(p, a); }
// ) * { p; }
rules.metaPostfix = Sequence.new()
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #metaPrimary)))
.push(Star.new(expression: Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #dot))
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(Assignment.new(name: #a, rule: RuleCall.new(name: #args)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Not.new(expression: RuleCall.new(name: #lbrace)))
.push(Action.new(parseTree: `{ p = Invoke.new(self: p, method: i, arguments: a); }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #dot))
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Action.new(parseTree: `{ p = GetProp.new(object: p, key: i); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #a, rule: RuleCall.new(name: #args)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Not.new(expression: RuleCall.new(name: #lbrace)))
.push(Action.new(parseTree: `{ p = Call.new(function: p, arguments: a); }))
// TODO: Voir si c'est toujours bon avec le newApply()
)
))
.push(Action.new(parseTree: `{ p; }));
// args = LPAREN a:mklist
// (
// ( k:metaId COLON e:metaExpression { Object_put(a, k, e); }
// | e:metaExpression { Object_push(a, e); }
// )
// ( COMMA
// ( k:metaId COLON e:metaExpression { Object_put(a, k, e); }
// | e:metaExpression { Object_push(a, e); }
// )
// ) *
// ) ? RPAREN { a; }
rules.args = Sequence.new()
.push(RuleCall.new(name: #lparen))
.push(Assignment.new(name: #a, rule: RuleCall.new(name: #mklist)))
.push(Optional.new(expression: Sequence.new()
.push(Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #k, rule: RuleCall.new(name: #metaId)))
.push(RuleCall.new(name: #colon))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ a[k] = e; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ a.push(e); }))
)
)
.push(Star.new(expression: Sequence.new()
.push(RuleCall.new(name: #comma))
.push(Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #k, rule: RuleCall.new(name: #metaId)))
.push(RuleCall.new(name: #colon))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ a[k] = e; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ a.push(e); }))
)
)
))
))
.push(RuleCall.new(name: #rparen))
.push(Action.new(parseTree: `{ a; }));
// mklist = { new(pObject); }
// metaPrimary = nil | metaVar | metaSubExpr
// metaSubExpr = LPAREN e:metaExpression RPAREN { e; }
rules.mklist = Action.new(parseTree: `{ Object.new(); });
rules.metaPrimary = Alternation.new()
.push(RuleCall.new(name: #nil))
.push(RuleCall.new(name: #metaVar))
.push(RuleCall.new(name: #metaSubExpr));
rules.metaSubExpr = Sequence.new()
.push(RuleCall.new(name: #lparen))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(RuleCall.new(name: #rparen))
.push(Action.new(parseTree = `{ e; }));
// metaBlock = LBRACE b:mklist
// ( e:metaStatement { b.push(e); }
// ) * RBRACE { b; }
rules.metaBlock = Sequence.new()
.push(RuleCall.new(name: #lbrace))
.push(Assignment.new(name: #b, rule: RuleCall.new(name: #mklist)))
.push(
Star.new(
expression: Sequence.new()
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaStatement)))
.push(Action.new(parseTree: `{ b.push(e); }))
)
)
.push(RuleCall.new(name: #rbrace))
.push(Action.new(parseTree: `{ Block.new(body: b); }));
// metaVar = i:metaId { newGetVar(i); }
// metaId = < LETTER ALNUM* > - { intern(yytext); }
rules.metaVar = Sequence.new()
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(Action.new(parseTree: `{ GetVar.new(name: i); }));
rules.metaId = Sequence.new()
.push(Begin.new())
.push(RuleCall.new(name: #letter))
.push(Star.new(expression: RuleCall.new(name: #alnum)))
.push(End.new())
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ intern(yytext); }));
// Literal Terminators
// BAR = '|' -
// NOT = '!' -
// QUERY = '?' -
// BEGIN = '<' -
// END = '>' -
// TILDE = '~' -
// RPERCENT = '%}' -
rules.bar = Sequence.new().push(StringLiteral.new(string: "|")).push(RuleCall.new(name: #ws));
rules.not = Sequence.new().push(StringLiteral.new(string: "!")).push(RuleCall.new(name: #ws));
rules.query = Sequence.new().push(StringLiteral.new(string: "?")).push(RuleCall.new(name: #ws));
rules.begin = Sequence.new().push(StringLiteral.new(string: "<")).push(RuleCall.new(name: #ws));
rules.end = Sequence.new().push(StringLiteral.new(string: ">")).push(RuleCall.new(name: #ws));
rules.tilde = Sequence.new().push(StringLiteral.new(string: "~")).push(RuleCall.new(name: #ws));
rules.rpercent = Sequence.new().push(StringLiteral.new(string: "%}")).push(RuleCall.new(name: #ws));
// DIGIT = [0-9]
// LETTER = [A-Za-z_]
// ALNUM = LETTER | DIGIT
// NIL = "nil" !ALNUM -
rules.digit = CharacterClass.new(value: "0-9");
rules.letter = CharacterClass.new(value: "A-Za-z_");
rules.alnum = Alternation.new()
.push(RuleCall.new(name: #letter))
.push(RuleCall.new(name: #digit));
rules.nil = Sequence.new()
.push(StringLiteral.new(string: "nil"))
.push(Not.new(expression: RuleCall.new(name: #alnum)))
.push(RuleCall.new(name: #ws));
// SEMI = ";" -
// COMMA = "," -
// COLON = ":" -
// LPAREN = "(" -
// RPAREN = ")" -
// LBRAK = "[" -
// RBRAK = "]" -
// LBRACE = "{" -
// RBRACE = "}" -
// ASSIGN = "=" ![=] -
// AND = "&" ![&=] -
// PLUS = "+" ![+=] -
// STAR = "*" ![=] -
// DOT = "." ![.] -
rules.semi = Sequence.new().push(StringLiteral.new(string: ";")).push(RuleCall.new(name: #ws));
rules.comma = Sequence.new().push(StringLiteral.new(string: ",")).push(RuleCall.new(name: #ws));
rules.colon = Sequence.new().push(StringLiteral.new(string: ":")).push(RuleCall.new(name: #ws));
rules.lparen = Sequence.new().push(StringLiteral.new(string: "(")).push(RuleCall.new(name: #ws));
rules.rparen = Sequence.new().push(StringLiteral.new(string: ")")).push(RuleCall.new(name: #ws));
rules.lbrak = Sequence.new().push(StringLiteral.new(string: "[")).push(RuleCall.new(name: #ws));
rules.rbrak = Sequence.new().push(StringLiteral.new(string: "]")).push(RuleCall.new(name: #ws));
rules.lbrace = Sequence.new().push(StringLiteral.new(string: "{")).push(RuleCall.new(name: #ws));
rules.rbrace = Sequence.new().push(StringLiteral.new(string: "}")).push(RuleCall.new(name: #ws));
rules.assign = Sequence.new()
.push(StringLiteral.new(string: "="))
.push(Not.new(expression: CharacterClass.new(value: "=")))
.push(RuleCall.new(name: #ws));
rules.and = Sequence.new()
.push(StringLiteral.new(string: "&"))
.push(Not.new(expression: CharacterClass.new(value: "&=")))
.push(RuleCall.new(name: #ws));
rules.plus = Sequence.new()
.push(StringLiteral.new(string: "+"))
.push(Not.new(expression: CharacterClass.new(value: "+=")))
.push(RuleCall.new(name: #ws));
rules.star = Sequence.new()
.push(StringLiteral.new(string: "*"))
.push(Not.new(expression: CharacterClass.new(value: "=")))
.push(RuleCall.new(name: #ws));
rules.dot = Sequence.new()
.push(StringLiteral.new(string: "."))
.push(Not.new(expression: CharacterClass.new(value: ".")))
.push(RuleCall.new(name: #ws));
// Whitespace
// - = ( space | comment )*
// space = ' ' | '\t' | end-of-line
// comment = '#' ( !end-of-line . )* end-of-line
// end-of-line = '\r\n' | '\n' | '\r'
// end-of-file = !.
rules.end_of_file = Not.new(expression: Dot.new());
rules.end_of_line = Alternation.new()
.push(StringLiteral.new(string: "\r\n"))
.push(StringLiteral.new(string: "\n"))
.push(StringLiteral.new(string: "\r"));
rules.comment = Sequence.new()
.push(StringLiteral.new(string: "#"))
.push(Star.new(expression:
Sequence.new()
.push(Not.new(expression: RuleCall.new(name: #end_of_line)))
.push(Dot.new())
))
.push(RuleCall.new(name: #end_of_line));
rules.space = Alternation.new()
.push(StringLiteral.new(string: " "))
.push(StringLiteral.new(string: "\t"))
.push(RuleCall.new(name: #end_of_line));
rules.ws = Star.new(expression: Alternation.new()
.push(RuleCall.new(name: #space))
.push(RuleCall.new(name: #comment))
);
// ----- Main -----
stream = newStream(readfile("rawgrammar.leg"));
context = Context.new(outerContext: nil).init();
actions = [];
print("\nMatching : ", rules.grammar.match(stream, context, rules, actions), "\n");
// Execute all actions after all matching
grammar = { for (actionAndContext in actions) {
actionAndContext.action.execute(actionAndContext.context);
}};
println(grammar);
stream2 = newStream(readfile("rawgrammar.leg"));
context2 = Context.new(outerContext: nil).init();
actions2 = [];
print("\nMatching : ", grammar.grammar.match(stream2, context2, grammar, actions2), "\n");
grammar2 = {
for (actionAndContext in actions2) {
grammar2 = actionAndContext.action.execute(actionAndContext.context);
}
};
println(grammar2);

+ 184
- 45
minproto.leg Ver arquivo

@ -1,6 +1,6 @@
# minproto.leg -- minimal prototype langauge for semantic experiments
#
# last edited: 2024-05-15 19:13:04 by piumarta on debian
# last edited: 2024-05-18 08:41:26 by piumarta on zora
%{
;
@ -99,9 +99,9 @@ oop printOn(oop buf, oop obj, int indent);
#endif
#if PRIMCLOSURE
#define doProtos(_) _(Object) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(Binop) _(Unyop) _(Let) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal)
#define doProtos(_) _(Object) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(Binop) _(Unyop) _(Let) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Range)
#else
#define doProtos(_) _(Object) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(Binop) _(Unyop) _(Let) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure)
#define doProtos(_) _(Object) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(Binop) _(Unyop) _(Let) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure) _(Range)
#endif
#define declareProto(NAME) oop p##NAME = 0;
@ -129,7 +129,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) _(__globals__)
#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) _(v) _(start) _(end) _(env)
#define declareSym(NAME) oop sym_##NAME = 0;
doSymbols(declareSym);
@ -212,6 +212,8 @@ union object _nil = { Undefined };
#define nil (&_nil)
oop namespaces = nil;
#define UNDEFINED 0
enum type getType(oop obj)
@ -414,6 +416,13 @@ char *String_content(oop str)
return _get(str, String,value);
}
oop String_concat(oop a, oop b)
{
oop result = newStringLen(_get(a, String,value), _get(a, String,length));
String_appendAllLen(result, _get(b, String,value), _get(b, String,length));
return result;
}
oop newStringEscaped(char *string)
{
oop buf = newStringLen(0, 0);
@ -432,6 +441,8 @@ oop newStringEscaped(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' : c = readCharValue(&string, 8, 3); break;
@ -686,38 +697,57 @@ oop Object_get(oop obj, oop key)
return nil;
}
oop *refvar(oop obj, oop key)
oop *_refvar(oop obj, oop key)
{
while (is(Object, obj)) {
ssize_t ind = Object_find(obj, key);
if (ind >= 0) return &_get(obj, Object,properties)[ind].val;
obj = _getDelegate(obj);
}
int numspaces = _get(namespaces, Object,isize);
if (numspaces) {
oop *nss = _get(namespaces, Object,indexed);
for (int i = numspaces; i--;) {
oop ns = nss[i];
while (is(Object, ns)) {
ssize_t ind = Object_find(ns, key);
if (ind >= 0) return &_get(ns, Object,properties)[ind].val;
ns = _getDelegate(ns);
}
}
}
oop *ref = &_get(key, Symbol,value); // asserts is(Symbol,key)
return ref;
}
oop *refvar(oop obj, oop key)
{
oop *ref = _refvar(obj, key);
if (UNDEFINED == *ref) fatal("undefined variable: %s", storeString(key, 0));
return ref;
}
oop getvar(oop obj, oop key)
{
while (is(Object, obj)) {
ssize_t ind = Object_find(obj, key);
if (ind >= 0) return _get(obj, Object,properties)[ind].val;
obj = _getDelegate(obj);
}
oop value = _get(key, Symbol,value); // asserts is(Symbol,key)
if (UNDEFINED == value) fatal("undefined variable: %s", storeString(key, 0));
return value;
return *refvar(obj, key);
}
oop Object_put(oop obj, oop key, oop val);
oop setvar(oop obj, oop key, oop val)
{
oop env = obj;
while (is(Object, obj)) {
ssize_t ind = Object_find(obj, key);
if (ind >= 0) return _get(obj, Object,properties)[ind].val = val;
obj = _getDelegate(obj);
}
return is(Symbol, key) ? _set(key, Symbol,value, val) : nil;
int numspaces = _get(namespaces, Object,isize);
if (numspaces) {
oop *nss = _get(namespaces, Object,indexed);
return Object_put(nss[numspaces - 1], key, val);
}
return _get(key, Symbol,value) = val; // asserts is(Symbol,key)
}
oop Object_put(oop obj, oop key, oop val)
@ -1161,12 +1191,12 @@ oop storeOn(oop buf, oop obj, int indent)
}
struct property *kvs = _get(obj, Object,properties);
size = _get(obj, Object,psize);
for (int i = 0; i < size; ++i) {
if (kvs[i].key == prop_delegate && kvs[i].val == pObject) continue;
if (i) String_appendAll(buf, ", ");
codeOn(buf, kvs[i].key, indent);
for (int j = 0; j < size; ++j) {
if (kvs[j].key == prop_delegate && kvs[j].val == pObject) continue;
if (i++) String_appendAll(buf, ", ");
codeOn(buf, kvs[j].key, indent);
String_appendAll(buf, ": ");
codeOn(buf, kvs[i].val, indent);
codeOn(buf, kvs[j].val, indent);
}
String_append(buf, ']');
break;
@ -1522,6 +1552,17 @@ oop GetArray_eval(oop exp, oop env)
default: fatal("[]: %s is not indexable", storeString(obj, 0));
}
}
if (getType(ind) == Object && Object_get(ind, prop_name) == Object_get(pRange, prop_name)) {
switch (getType(obj)) {
case String: {
int start = integerValue(eval(Object_get(ind, sym_start), env), "[..]");
int end = integerValue(eval(Object_get(ind, sym_end ), env), "[..]");
oop slice = newStringLen(String_aref(obj, start), end - start);
return slice;
}
default: fatal("[]: %s is not range - indexable", storeString(obj, 0));
}
}
if (!is(Object, obj)) fatal("[]: %s is not an object", storeString(obj, 0));
return Object_getLocal(obj, ind);
}
@ -1571,6 +1612,25 @@ void SetArray_codeOn(oop exp, oop str, oop env)
codeOn(str, Object_get(exp, sym_value), 0);
}
oop newRange(oop start, oop end) {
oop o = new(pRange);
Object_put(o, sym_start, start);
Object_put(o, sym_end, end);
return o;
}
oop Range_eval(oop exp, oop env)
{
return exp;
}
void Range_codeOn(oop exp, oop str, oop env)
{
codeOn(str, Object_get(exp, sym_start), 0);
String_appendAll(str, "..");
codeOn(str, Object_get(exp, sym_end), 0);
}
oop newCall(oop function, oop arguments)
{
oop o = new(pCall);
@ -1990,6 +2050,16 @@ oop binShr(oop l, oop r)
return 0;
}
oop binAdd(oop l, oop r)
{
int tl = getType(l), tr = getType(r);
if (Integer == tl && Integer == tr) return newInteger(_integerValue(l ) + _integerValue(r ));
if (Float == tl || Float == tr) return newFloat ( floatValue (l, "+") + floatValue (r, "+"));
if (String == tl && String == tr) return String_concat(l, r);
fatal("+: illegal operand types %s and %s", getTypeName(l), getTypeName(r));
return 0;
}
#define binop(NAME, OP) \
oop NAME(oop l, oop r) \
{ \
@ -2000,7 +2070,6 @@ oop NAME(oop l, oop r)
return 0; \
}
binop(binAdd, +);
binop(binSub, -);
binop(binMul, *);
@ -2703,6 +2772,7 @@ stmt = LET l:mklet k:id ASSIGN v:expr { Let_append(l, k, v) }
u:expr RPAREN s:stmt { $$ = newFor(i, c, u, s) }
| i:id p:params b:block { $$ = newSetVar(i, newLambda(p, b)) }
| v:proto DOT i:id p:params b:block { $$ = newSetProp(v, i, newLambda(p, b)) }
| v:proto CCOLON i:id p:params b:block { $$ = newSetProp(v, i, newLambda(p, b)) }
| b:block { $$ = newBlock(b) }
| e:expr EOS { $$ = e }
@ -2760,10 +2830,13 @@ 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: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 = newRange(i1, i2) }
) ? { $$ = i1 }
prefix = PPLUS p:prefix { $$ = newBinop(opPreAdd, lvalue(p), newInteger(1)) }
| MMINUS p:prefix { $$ = newBinop(opPreSub, lvalue(p), newInteger(1)) }
@ -2780,6 +2853,7 @@ postfix = p:primary
| { p = newGetProp(p, i) }
)
| a:args !LBRACE { p = newApply(p, a) }
| CCOLON i:id { p = newGetProp(p, i) }
)*
( PPLUS { p = newBinop(opPostAdd, lvalue(p), newInteger( 1)) }
| MMINUS { p = newBinop(opPostAdd, lvalue(p), newInteger(-1)) }
@ -2831,8 +2905,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)) }
@ -2886,7 +2959,8 @@ HASH = "#" -
SEMI = ";" -
ASSIGN = "=" ![=] -
COMMA = "," -
COLON = ":" -
COLON = ":" ![:] -
CCOLON = "::" -
LPAREN = "(" -
RPAREN = ")" -
LBRAK = "[" -
@ -2923,7 +2997,8 @@ SLASH = "/" ![/=] -
SLASHEQ = "/=" -
PCENT = "%" ![=] -
PCENTEQ = "%=" -
DOT = "." -
DOT = "." ![.] -
DOTDOT = ".." -
PLING = "!" ![=] -
TILDE = "~" -
@ -3070,7 +3145,7 @@ oop eval(oop exp, oop env)
# if PRIMCLOSURE
if (Lambda == type) return newClosure(exp, env);
# endif
if (Object != getType(exp)) return exp;
if (Object != type) return exp;
if (!opt_O) Object_push(trace, exp);
oop result = evalobj(exp, env);
if (!opt_O) Object_pop(trace);
@ -3155,6 +3230,11 @@ 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)) {
env = Object_getLocal(args, sym_env);
}
for (int i = 0; i < argc; ++i) result = eval(indexed[i], env);
return result;
}
@ -3164,6 +3244,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);
@ -3253,6 +3349,15 @@ oop prim_chr(oop func, oop self, oop args, oop env)
return str;
}
oop prim_escapeString(oop func, oop self, oop args, oop env)
{
int argc = _get(args, Object,isize);
if (1 != argc) fatal("escapeString: 1 argument expected");
oop arg = _get(args, Object,indexed)[0];
if (!is(String, arg)) fatal("escapeString: string argument expected");
return newStringEscaped(String_content(arg));
}
void readFile(FILE *file, char **textp, int *sizep)
{
size_t size = 0;
@ -3296,6 +3401,35 @@ oop prim_exit(oop func, oop self, oop args, oop env)
return nil;
}
oop prim_error(oop func, oop self, oop args, oop env)
{
int argc = _get(args, Object,isize);
if (argc != 1) fatal("error: one argument expected");
oop arg = _get(args, Object,indexed)[0];
if (!is(String, arg)) fatal("error: non-string argument");
fatal("%.*s", _get(arg, String,length), _get(arg, String,value));
return 0;
}
oop prim_Symbol_setopt(oop func, oop self, oop args, oop env)
{ assert(is(Symbol, self));
int argc = _get(args, Object,isize);
if (argc != 1) fatal("setopt: one argument expected");
oop val = _get(args, Object,indexed)[0];
if (!isInteger(val)) fatal("setopt: non-integer option value: %s", storeString(val, 0));
int optval = _integerValue(val);
if (sym_O == self) opt_O = optval;
else if (sym_d == self) opt_d = optval;
else if (sym_v == self) opt_v = optval;
else fatal("setopt: unknown option: %s", storeString(self, 0));
return val;
}
oop prim_Symbol_defined(oop func, oop self, oop args, oop env)
{
return *_refvar(env, self) ? sym_t : nil;
}
oop replFile(FILE *in)
{
int oldline = lineno;
@ -3315,7 +3449,7 @@ oop replFile(FILE *in)
printf(">>> ");
(opt_d ? println : codeln)(yysval, opt_v >2);
}
result = eval(yysval, _get(sym___globals__, Symbol,value));
result = eval(yysval, nil);
if (opt_v) {
printf("==> ");
if (opt_v >= 3) storeln(result, 1);
@ -3393,20 +3527,23 @@ int main(int argc, char **argv)
# define prim(NAME, FUNC) _set(intern(#NAME), Symbol,value, newPrimitive(FUNC, newString(#NAME)))
prim(__env__ , prim_env);
prim(eval , prim_eval);
prim(print , prim_print);
prim(codeString , prim_codeString);
prim(sqrt , prim_sqrt);
prim(round , prim_round);
prim(truncate , prim_truncate);
prim(cputime , prim_cputime);
prim(evaluations, prim_evaluations);
prim(len , prim_len);
prim(ord , prim_ord);
prim(chr , prim_chr);
prim(readfile , prim_readfile);
prim(exit , prim_exit);
prim(__env__ , prim_env);
prim(eval , prim_eval);
prim(print , prim_print);
prim(codeString , prim_codeString);
prim(sqrt , prim_sqrt);
prim(round , prim_round);
prim(truncate , prim_truncate);
prim(cputime , prim_cputime);
prim(evaluations , prim_evaluations);
prim(len , prim_len);
prim(ord , prim_ord);
prim(chr , prim_chr);
prim(readfile , prim_readfile);
prim(exit , prim_exit);
prim(fatal , prim_error);
prim(intern , prim_intern);
prim(escapeString , prim_escapeString);
# undef prim
@ -3419,10 +3556,12 @@ int main(int argc, char **argv)
method(Object,keys, prim_keys );
method(Object,allKeys, prim_allKeys);
method(Object,sorted, prim_sorted );
method(Symbol,defined, prim_Symbol_defined);
method(Symbol,setopt, prim_Symbol_setopt);
# undef method
_set(sym___globals__, Symbol,value, nil);
namespaces = _set(sym___namespaces__, Symbol,value, new(pObject));
trace = new(pObject);

+ 134
- 0
rawgrammar.leg Ver arquivo

@ -0,0 +1,134 @@
grammar = - g:mklist
( d:definition { g[d.name] = d.expression; }
) + end-of-file { g; }
definition = i:identifier ASSIGN e:expression SEMI? { Definition.new(name: i, expression: e); }
expression = s1:sequence { s1 = Alternation.new().push(s1); }
( BAR s2:sequence { s1.push(s2); }
) * { s1; }
sequence = p:prefix { p = Sequence.new().push(p); }
( q:prefix { p.push(q); }
) * { p; }
prefix = AND a:action { ParseTimeAction.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:ruleCallIdent !ASSIGN { Assignment.new(name: i1, rule: i2); }
| i:ruleCallIdent !ASSIGN { i; }
| LPAREN e:expression RPAREN { e; }
| l:literal { l; }
| c:class { c; }
| DOT { Dot.new(); }
| a:action { a; }
| BEGIN { Begin.new(); }
| END { End.new(); }
identifier = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { intern(yytext); }
ruleCallIdent = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { RuleCall.new(name: intern(yytext)); }
literal = ['] < ( !['] char )* > ['] - { StringLiteral.new(value: yytext); }
| ["] < ( !["] char )* > ["] - { StringLiteral.new(value: 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:metaBlock - { Action.new(parseTree: 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 = !.
metaStatement = b:metaBlock { b; }
| e:metaExpression SEMI { e; }
metaExpression = p:metaPrimary
( DOT i:metaId ASSIGN e:metaExpression # { $$ = newSetProp(p, i, e) }
| LBRAK i:metaExpression RBRAK ASSIGN e:metaExpression { SetArray.new(object: p, index: i, value: e); }
)
| i:metaId ASSIGN e:metaExpression { SetVar.new(name: i, value: e); }
| pf:metaPostfix { pf; }
metaPostfix = p:metaPrimary
( DOT i:metaId a:args !ASSIGN !LBRACE { p = Invoke.new(self: p, method: i, arguments: a); }
| DOT i:metaId !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:metaId COLON e:metaExpression { a[k] = e; }
| e:metaExpression { a.push(e); }
)
( COMMA
( k:metaId COLON e:metaExpression { a[k] = e; }
| e:metaExpression { a.push(e); }
)
) *
) ? RPAREN { a; }
mklist = { Object.new(); }
metaPrimary = nil | metaVar | metaSubExpr
metaSubExpr = LPAREN e:metaExpression RPAREN { e; }
metaBlock = LBRACE b:mklist
( e:metaStatement { b.push(e); }
) * RBRACE { Block.new(body: b); }
nil = NIL { nil; }
metaVar = i:metaId { GetVar.new(name: i); }
metaId = < LETTER ALNUM* > - { intern(yytext); }
DIGIT = [0-9]
LETTER = [A-Za-z_]
ALNUM = LETTER | DIGIT
BAR = '|' -
NOT = '!' -
QUERY = '?' -
BEGIN = '<' -
END = '>' -
TILDE = '~' -
RPERCENT = '%}' -
NIL = "nil" !ALNUM -
SEMI = ";" -
ASSIGN = "=" ![=] -
COMMA = "," -
COLON = ":" -
LPAREN = "(" -
RPAREN = ")" -
LBRAK = "[" -
RBRAK = "]" -
LBRACE = "{" -
RBRACE = "}" -
AND = "&" ![&=] -
PLUS = "+" ![+=] -
STAR = "*" ![=] -
DOT = "." ![.] -

Carregando…
Cancelar
Salvar