10 コミット

5個のファイルの変更1276行の追加48行の削除
  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 ファイルの表示

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

+ 2
- 2
bench-sieve.txt ファイルの表示

@ -2,8 +2,8 @@
// 178589010 nodes evaluated in 2.129754 seconds = 83854290 nodes/sec // 178589010 nodes evaluated in 2.129754 seconds = 83854290 nodes/sec
// 178589010 nodes evaluated in 2.126711 seconds = 83974273 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; count = 0;

+ 948
- 0
grammar_parser.meta ファイルの表示

@ -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 ファイルの表示

@ -1,6 +1,6 @@
# minproto.leg -- minimal prototype langauge for semantic experiments # 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 #endif
#if PRIMCLOSURE #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 #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 #endif
#define declareProto(NAME) oop p##NAME = 0; #define declareProto(NAME) oop p##NAME = 0;
@ -129,7 +129,7 @@ doTypes(makeProto);
doProperties(declareProp); doProperties(declareProp);
#undef 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; #define declareSym(NAME) oop sym_##NAME = 0;
doSymbols(declareSym); doSymbols(declareSym);
@ -212,6 +212,8 @@ union object _nil = { Undefined };
#define nil (&_nil) #define nil (&_nil)
oop namespaces = nil;
#define UNDEFINED 0 #define UNDEFINED 0
enum type getType(oop obj) enum type getType(oop obj)
@ -414,6 +416,13 @@ char *String_content(oop str)
return _get(str, String,value); 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 newStringEscaped(char *string)
{ {
oop buf = newStringLen(0, 0); oop buf = newStringLen(0, 0);
@ -432,6 +441,8 @@ oop newStringEscaped(char *string)
case 'r' : c = '\r'; break; case 'r' : c = '\r'; break;
case 't' : c = '\t'; break; case 't' : c = '\t'; break;
case 'v' : c = '\v'; break; case 'v' : c = '\v'; break;
case '[' : c = '[' ; break;
case ']' : c = ']' ; break;
case 'X' : case 'X' :
case 'x' : c = readCharValue(&string, 16, -1); break; case 'x' : c = readCharValue(&string, 16, -1); break;
case '0' : c = readCharValue(&string, 8, 3); break; case '0' : c = readCharValue(&string, 8, 3); break;
@ -686,38 +697,57 @@ oop Object_get(oop obj, oop key)
return nil; return nil;
} }
oop *refvar(oop obj, oop key)
oop *_refvar(oop obj, oop key)
{ {
while (is(Object, obj)) { while (is(Object, obj)) {
ssize_t ind = Object_find(obj, key); ssize_t ind = Object_find(obj, key);
if (ind >= 0) return &_get(obj, Object,properties)[ind].val; if (ind >= 0) return &_get(obj, Object,properties)[ind].val;
obj = _getDelegate(obj); 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) 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)); if (UNDEFINED == *ref) fatal("undefined variable: %s", storeString(key, 0));
return ref; return ref;
} }
oop getvar(oop obj, oop key) 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 setvar(oop obj, oop key, oop val)
{ {
oop env = obj;
while (is(Object, obj)) { while (is(Object, obj)) {
ssize_t ind = Object_find(obj, key); ssize_t ind = Object_find(obj, key);
if (ind >= 0) return _get(obj, Object,properties)[ind].val = val; if (ind >= 0) return _get(obj, Object,properties)[ind].val = val;
obj = _getDelegate(obj); 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) 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); struct property *kvs = _get(obj, Object,properties);
size = _get(obj, Object,psize); 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, ": "); String_appendAll(buf, ": ");
codeOn(buf, kvs[i].val, indent);
codeOn(buf, kvs[j].val, indent);
} }
String_append(buf, ']'); String_append(buf, ']');
break; break;
@ -1522,6 +1552,17 @@ oop GetArray_eval(oop exp, oop env)
default: fatal("[]: %s is not indexable", storeString(obj, 0)); 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)); if (!is(Object, obj)) fatal("[]: %s is not an object", storeString(obj, 0));
return Object_getLocal(obj, ind); 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); 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 newCall(oop function, oop arguments)
{ {
oop o = new(pCall); oop o = new(pCall);
@ -1990,6 +2050,16 @@ oop binShr(oop l, oop r)
return 0; 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) \ #define binop(NAME, OP) \
oop NAME(oop l, oop r) \ oop NAME(oop l, oop r) \
{ \ { \
@ -2000,7 +2070,6 @@ oop NAME(oop l, oop r)
return 0; \ return 0; \
} }
binop(binAdd, +);
binop(binSub, -); binop(binSub, -);
binop(binMul, *); 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) } u:expr RPAREN s:stmt { $$ = newFor(i, c, u, s) }
| i:id p:params b:block { $$ = newSetVar(i, newLambda(p, b)) } | 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 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) } | b:block { $$ = newBlock(b) }
| e:expr EOS { $$ = e } | 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) } | MINUS r:prod { l = newBinop(opSub, l, r) }
)* { $$ = l } )* { $$ = 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)) } prefix = PPLUS p:prefix { $$ = newBinop(opPreAdd, lvalue(p), newInteger(1)) }
| MMINUS p:prefix { $$ = newBinop(opPreSub, lvalue(p), newInteger(1)) } | MMINUS p:prefix { $$ = newBinop(opPreSub, lvalue(p), newInteger(1)) }
@ -2780,6 +2853,7 @@ postfix = p:primary
| { p = newGetProp(p, i) } | { p = newGetProp(p, i) }
) )
| a:args !LBRACE { p = newApply(p, a) } | a:args !LBRACE { p = newApply(p, a) }
| CCOLON i:id { p = newGetProp(p, i) }
)* )*
( PPLUS { p = newBinop(opPostAdd, lvalue(p), newInteger( 1)) } ( PPLUS { p = newBinop(opPostAdd, lvalue(p), newInteger( 1)) }
| MMINUS { 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:number { $$ = n }
| n:unsign { $$ = 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" [bB] < BIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 2)) }
| "0" [xX] < HIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 16)) } | "0" [xX] < HIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 16)) }
| "0" < OIGIT* > - { $$ = newInteger(strtol(yytext, 0, 8)) } | "0" < OIGIT* > - { $$ = newInteger(strtol(yytext, 0, 8)) }
@ -2886,7 +2959,8 @@ HASH = "#" -
SEMI = ";" - SEMI = ";" -
ASSIGN = "=" ![=] - ASSIGN = "=" ![=] -
COMMA = "," - COMMA = "," -
COLON = ":" -
COLON = ":" ![:] -
CCOLON = "::" -
LPAREN = "(" - LPAREN = "(" -
RPAREN = ")" - RPAREN = ")" -
LBRAK = "[" - LBRAK = "[" -
@ -2923,7 +2997,8 @@ SLASH = "/" ![/=] -
SLASHEQ = "/=" - SLASHEQ = "/=" -
PCENT = "%" ![=] - PCENT = "%" ![=] -
PCENTEQ = "%=" - PCENTEQ = "%=" -
DOT = "." -
DOT = "." ![.] -
DOTDOT = ".." -
PLING = "!" ![=] - PLING = "!" ![=] -
TILDE = "~" - TILDE = "~" -
@ -3070,7 +3145,7 @@ oop eval(oop exp, oop env)
# if PRIMCLOSURE # if PRIMCLOSURE
if (Lambda == type) return newClosure(exp, env); if (Lambda == type) return newClosure(exp, env);
# endif # endif
if (Object != getType(exp)) return exp;
if (Object != type) return exp;
if (!opt_O) Object_push(trace, exp); if (!opt_O) Object_push(trace, exp);
oop result = evalobj(exp, env); oop result = evalobj(exp, env);
if (!opt_O) Object_pop(trace); 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); int argc = _get(args, Object,isize);
oop *indexed = _get(args, Object,indexed); oop *indexed = _get(args, Object,indexed);
oop result = nil; 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); for (int i = 0; i < argc; ++i) result = eval(indexed[i], env);
return result; return result;
} }
@ -3164,6 +3244,22 @@ oop prim___eval__(oop func, oop self, oop args, oop env)
return self; 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) oop prim_print(oop func, oop self, oop args, oop env)
{ {
int argc = _get(args, Object,isize); int argc = _get(args, Object,isize);
@ -3253,6 +3349,15 @@ oop prim_chr(oop func, oop self, oop args, oop env)
return str; 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) void readFile(FILE *file, char **textp, int *sizep)
{ {
size_t size = 0; size_t size = 0;
@ -3296,6 +3401,35 @@ oop prim_exit(oop func, oop self, oop args, oop env)
return nil; 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) oop replFile(FILE *in)
{ {
int oldline = lineno; int oldline = lineno;
@ -3315,7 +3449,7 @@ oop replFile(FILE *in)
printf(">>> "); printf(">>> ");
(opt_d ? println : codeln)(yysval, opt_v >2); (opt_d ? println : codeln)(yysval, opt_v >2);
} }
result = eval(yysval, _get(sym___globals__, Symbol,value));
result = eval(yysval, nil);
if (opt_v) { if (opt_v) {
printf("==> "); printf("==> ");
if (opt_v >= 3) storeln(result, 1); 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))) # 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 # undef prim
@ -3419,10 +3556,12 @@ int main(int argc, char **argv)
method(Object,keys, prim_keys ); method(Object,keys, prim_keys );
method(Object,allKeys, prim_allKeys); method(Object,allKeys, prim_allKeys);
method(Object,sorted, prim_sorted ); method(Object,sorted, prim_sorted );
method(Symbol,defined, prim_Symbol_defined);
method(Symbol,setopt, prim_Symbol_setopt);
# undef method # undef method
_set(sym___globals__, Symbol,value, nil);
namespaces = _set(sym___namespaces__, Symbol,value, new(pObject));
trace = new(pObject); trace = new(pObject);

+ 134
- 0
rawgrammar.leg ファイルの表示

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

読み込み中…
キャンセル
保存