瀏覽代碼

Default grammar is part of PEG VM frame. RULE2 and CALL2 change the default grammar for the duration of the rule being called.

master
Ian Piumarta 1 年之前
父節點
當前提交
1acd725af0
共有 1 個檔案被更改,包括 30 行新增9 行删除
  1. +30
    -9
      minproto.leg

+ 30
- 9
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-07-05 17:16:16 by piumarta on zora-1034.local
# last edited: 2024-07-10 11:28:02 by piumarta on zora-1034.local
%{ %{
; ;
@ -4770,12 +4770,12 @@ oop applyThunkIn(oop func, oop env)
typedef unsigned char byte; typedef unsigned char byte;
typedef enum op_t { typedef enum op_t {
PUSH, DROP, POP, DOT, CLASS, STRING, TEST, RULE2, RULE, CALL,
PUSH, DROP, POP, DOT, CLASS, STRING, TEST, RULE2, RULE, CALL, CALL2,
SUCCEED, FAIL, ACTION, BEGIN, END, UNEND, SET, SUCCEED, FAIL, ACTION, BEGIN, END, UNEND, SET,
} op_t; } op_t;
char *op_n[] = { char *op_n[] = {
"PUSH", "DROP", "POP", "DOT", "CLASS", "STRING", "TEST", "RULE2", "RULE", "CALL",
"PUSH", "DROP", "POP", "DOT", "CLASS", "STRING", "TEST", "RULE2", "RULE", "CALL", "CALL2",
"SUCCEED", "FAIL", "ACTION", "BEGIN", "END", "UNEND", "SET", "SUCCEED", "FAIL", "ACTION", "BEGIN", "END", "UNEND", "SET",
}; };
@ -4838,6 +4838,10 @@ void vmDisassemble(vmInsn *code, int pc)
printf("%03d %-7s %p %2d %2d %2d\n", printf("%03d %-7s %p %2d %2d %2d\n",
pc, op_n[i->op], i->arg.code, i->arg2.len, i->ok, i->ko); pc, op_n[i->op], i->arg.code, i->arg2.len, i->ok, i->ko);
break; break;
case CALL2:
printf("%03d %-7s %p %2d %2d %2d\n",
pc, op_n[i->op], i->arg.code, i->arg2.len, i->ok, i->ko);
break;
default: default:
printf("%03d %-7s %s %2d %2d %2d\n", printf("%03d %-7s %s %2d %2d %2d\n",
pc, op_n[i->op], codeString(i->arg.obj, 0), i->arg2.len, i->ok, i->ko); pc, op_n[i->op], codeString(i->arg.obj, 0), i->arg2.len, i->ok, i->ko);
@ -4906,6 +4910,10 @@ vmInsn *vmCompile(oop grammar, oop symbol)
valueError("__match__", "program contains explicit CALL opcode", program); valueError("__match__", "program contains explicit CALL opcode", program);
break; break;
} }
case CALL2: {
valueError("__match__", "program contains explicit CALL2 opcode", program);
break;
}
case ACTION: { case ACTION: {
if (!isClosure(code[cpc].arg.obj)) valueError("__match__", "ACTION argument must be a closure", program); if (!isClosure(code[cpc].arg.obj)) valueError("__match__", "ACTION argument must be a closure", program);
break; break;
@ -4944,12 +4952,10 @@ vmInsn *vmCacheGet(oop grammar, oop symbol)
return vmCompile(grammar, symbol); return vmCompile(grammar, symbol);
} }
int vmRun(oop grammar, oop symbol, char *text, int start, int length)
int vmRun(oop grammar0, oop symbol, char *text, int start, int length)
{ {
vmCache = new(pObject); vmCache = new(pObject);
vmInsn *code = vmCacheGet(grammar, symbol);
int maxactions = 32; int maxactions = 32;
struct Action { struct Action {
@ -4977,7 +4983,10 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length)
actions[context.nactions++] = (struct Action){ ACT, OBJ, BEG, LEN }; \ actions[context.nactions++] = (struct Action){ ACT, OBJ, BEG, LEN }; \
} }
//vmInsn *code = vmCacheGet(frame.grammar, symbol);
struct Frame { struct Frame {
oop grammar;
oop symbol; oop symbol;
vmInsn *code; vmInsn *code;
int pc; int pc;
@ -4986,8 +4995,9 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length)
int rsp = 0, nrstack = 32; int rsp = 0, nrstack = 32;
rstack = xmalloc(sizeof(*rstack) * nrstack); rstack = xmalloc(sizeof(*rstack) * nrstack);
frame.grammar = grammar0;
frame.symbol = symbol; frame.symbol = symbol;
frame.code = vmCacheGet(grammar, symbol);
frame.code = vmCacheGet(grammar0, symbol);
frame.pc = 0; frame.pc = 0;
frame.nactions = context.nactions; frame.nactions = context.nactions;
@ -5054,8 +5064,19 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length)
continue; continue;
} }
case RULE2: { case RULE2: {
i->op = CALL;
i->op = CALL2;
i->arg.code = vmCacheGet(i->arg2.obj, i->arg.obj); i->arg.code = vmCacheGet(i->arg2.obj, i->arg.obj);
goto doCall2; // (just in case they are not consecutive ;-))
case CALL2: { doCall2:
frame.pc--; // save pc of call insn
push(r, frame);
frame.grammar = i->arg2.obj;
frame.code = i->arg.code;
frame.pc = 0;
saveAction(vmEnter, nil, 0, 0);
frame.nactions = context.nactions;
continue;
}
goto doCall; goto doCall;
} }
case RULE: { case RULE: {
@ -5072,7 +5093,7 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length)
//i->arglen = ((Node *)i->arg)->Symbol.nvars; //i->arglen = ((Node *)i->arg)->Symbol.nvars;
//i->arg = ((Node *)i->arg)->Symbol.code; assert(i->arg); //i->arg = ((Node *)i->arg)->Symbol.code; assert(i->arg);
i->op = CALL; i->op = CALL;
i->arg.code = vmCacheGet(grammar, i->arg.obj);
i->arg.code = vmCacheGet(frame.grammar, i->arg.obj);
goto doCall; // (just in case they are not consecutive ;-)) goto doCall; // (just in case they are not consecutive ;-))
} }
case CALL: { doCall: case CALL: { doCall:

Loading…
取消
儲存