summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-13 14:45:13 +0300
committerKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-13 14:45:13 +0300
commita104f80e61f7e6a110a209cf7cc5ffd09d6b5b4f (patch)
treeb5282c35b4e50a1cd0e08f54c8de35d64ae9bd1c
parent70c48bade8529b4b5f762754db96982c8c95c31a (diff)
Add variable substitution
-rw-r--r--appl/cmd/sh92.b40
-rw-r--r--appl/lib/sh9parser.b94
-rw-r--r--module/sh9parser.m8
3 files changed, 129 insertions, 13 deletions
diff --git a/appl/cmd/sh92.b b/appl/cmd/sh92.b
index fe53ceb..1e865b9 100644
--- a/appl/cmd/sh92.b
+++ b/appl/cmd/sh92.b
@@ -165,6 +165,11 @@ tokenize(line: string, line_n: int): array of ref TokNode {
stmt_assign(c: ref ParserCtx, toks: array of ref TokNode): array of ref TokNode {
sys->print("ASSIGN STMT\n");
+ m:= c.get_current_module();
+ v:= ref ModVar;
+ v.name= toks[0].tok;
+ v.val= toks[2].tok;
+ m.set_var(v);
return array[0] of ref TokNode;
}
@@ -173,25 +178,47 @@ stmt_cmd_call(c: ref ParserCtx, toks: array of ref TokNode): array of ref TokNod
return array[0] of ref TokNode;
}
+sqstr_to_expr(c: ref ParserCtx, toks: array of ref TokNode): array of ref TokNode {
+ tn:= mk_tok(toks[0].start, toks[0].line, toks[0].tok, S_EXPR);
+ return array[1] of {tn};
+}
+
empty(c: ref ParserCtx, toks: array of ref TokNode): array of ref TokNode {
return array[0] of ref TokNode;
}
var_sub_expr(c: ref ParserCtx, toks: array of ref TokNode): array of ref TokNode {
sys->print("VAR SUB\n");
- return array[0] of ref TokNode;
+ varname:=toks[1].tok;
+ if (varname == "{") {
+ varname = toks[2].tok;
+ }
+ v:= c.find_var_in_current_module(varname);
+ if (v == nil) {
+ sys->print("Var %s is nil\nAll vars:\n", varname);
+ c.print_all_vars();
+ }
+ sys->print("VAR %s SUB: %s\n", v.name, v.val);
+ tn:= mk_tok(toks[0].start, toks[0].line, v.val, S_EXPR);
+ return array[1] of {tn};
}
+expr_expr_combiner(c: ref ParserCtx, toks: array of ref TokNode): array of ref TokNode {
+ comb_tok:= toks[0].tok + " " + toks[1].tok;
+ tn:= mk_tok(toks[0].start, toks[0].line, comb_tok, S_EXPR);
+ return array[1] of {tn};
+}
mk_grammar(ctx: ref ParserCtx): array of ref GrammarNode
{
semic_eol_g : GrammarNode = (array [] of {S_SEMIC, S_EOL}, S_EOL, empty, ctx);
assign_g_semic : GrammarNode = (array [] of {S_ID, S_EQ, S_EXPR, S_SEMIC}, S_NONE, stmt_assign, ctx);
assign_g_eol : GrammarNode = (array [] of {S_ID, S_EQ, S_EXPR, S_EOL}, S_NONE, stmt_assign, ctx);
- sqstr_expr_g: GrammarNode = (array [] of {S_SQSTR}, S_EXPR, empty, ctx);
+ sqstr_expr_g: GrammarNode = (array [] of {S_SQSTR}, nil, sqstr_to_expr, ctx);
str_expr_g: GrammarNode = (array [] of {S_STR}, S_EXPR, empty, ctx);
- expr_combinator_g: GrammarNode = (array [] of {S_EXPR, S_EXPR}, S_EXPR, empty, ctx);
- cmd_call_g: GrammarNode = (array [] of {S_ID, S_EXPR, S_SEMIC}, nil, stmt_cmd_call, ctx);
+ expr_combinator_g: GrammarNode = (array [] of {S_EXPR, S_EXPR}, nil, expr_expr_combiner, ctx);
+ cmd_call_semic_g: GrammarNode = (array [] of {S_ID, S_EXPR, S_SEMIC}, nil, stmt_cmd_call, ctx);
+ cmd_call_eol_g: GrammarNode = (array [] of {S_ID, S_EXPR, S_EOL}, nil, stmt_cmd_call, ctx);
var_sub_g: GrammarNode = (array [] of {S_DOLL, S_ID}, nil, var_sub_expr, ctx);
var_sub_curl_g: GrammarNode = (array [] of {S_DOLL, S_LCURLY, S_ID, S_RCURLY}, nil, var_sub_expr, ctx);
@@ -204,7 +231,8 @@ mk_grammar(ctx: ref ParserCtx): array of ref GrammarNode
ref assign_g_eol,
ref sqstr_expr_g,
ref str_expr_g,
- ref cmd_call_g,
+ ref cmd_call_semic_g,
+ ref cmd_call_eol_g,
ref expr_combinator_g,
ref var_sub_g,
ref var_sub_curl_g,
@@ -221,7 +249,7 @@ init(ctxt: ref Draw->Context, argv: list of string) {
pctx:= ref ParserCtx;
pctx.add_module("shell");
- toks1 := tokenize("AB = 'smth \"test\" ';", 0);
+ toks1 := tokenize("AB = 'smth \"test\" '; echo ${AB}; echo $AB", 0);
#print_toks(toks1);
#sys->print("Parse\n");
grammar:= mk_grammar(pctx);
diff --git a/appl/lib/sh9parser.b b/appl/lib/sh9parser.b
index 8df4cfc..54c26b5 100644
--- a/appl/lib/sh9parser.b
+++ b/appl/lib/sh9parser.b
@@ -26,13 +26,87 @@ GrammarNode.print_expr(gn: self ref GrammarNode)
}
}
+ShModule.find_var(m: self ref ShModule, name: string): ref ModVar
+{
+ l:= len m.vars;
+ vars := m.vars;
+ for (i:=0; i<l; i++) {
+ v := hd vars;
+ if (v.name == name) {
+ return v;
+ }
+ vars = tl vars;
+ }
+ return nil;
+}
+
+ShModule.print_vars(m: self ref ShModule)
+{
+ l:= len m.vars;
+ vars := m.vars;
+ for (i:=0; i<l; i++) {
+ v := hd vars;
+ sys->print("%s: %s\n", v.name, v.val);
+ vars = tl vars;
+ }
+}
+
+ShModule.set_var(m: self ref ShModule, v: ref ModVar)
+{
+ m.vars = v :: m.vars;
+}
+
ParserCtx.add_module(ctx: self ref ParserCtx, name: string)
{
m:= ref ShModule;
m.name = name;
+ if (ctx.current_module == nil) {
+ sys->print("Set current module %s\n", name);
+ ctx.current_module = name;
+ }
ctx.modules = m :: ctx.modules;
}
+ParserCtx.find_module(ctx: self ref ParserCtx, name: string): ref ShModule
+{
+ l:= len ctx.modules;
+ mods := ctx.modules;
+ for (i:=0; i<l; i++) {
+ m := hd mods;
+ if (m.name == name) {
+ return m;
+ }
+ mods = tl mods;
+ }
+ return nil;
+}
+
+ParserCtx.find_var_in_current_module(ctx: self ref ParserCtx, name: string): ref ModVar
+{
+ m := ctx.find_module(ctx.current_module);
+ if (m == nil) {
+ return nil;
+ }
+ return m.find_var(name);
+}
+
+ParserCtx.print_all_vars(ctx: self ref ParserCtx)
+{
+ l:= len ctx.modules;
+ mods := ctx.modules;
+ for (i:=0; i<l; i++) {
+ m := hd mods;
+ m.print_vars();
+ mods = tl mods;
+ }
+}
+
+ParserCtx.get_current_module(ctx: self ref ParserCtx): ref ShModule
+{
+ m := ctx.find_module(ctx.current_module);
+ return m;
+}
+
init()
{
sys = load Sys Sys->PATH;
@@ -127,24 +201,30 @@ parse_toks(toks: array of ref TokNode, g: array of ref GrammarNode): array of re
do
{
lt := len toks;
- #sys->print("Loop %d: ", ctr);
- #print_toks_short(toks);
+ sys->print("Loop %d: ", ctr);
+ print_toks_short(toks);
ctr ++;
changed = 0;
- fast: for (i := 0; i <= lt; i ++) {
+ fast: for (i := 0; i < lt; i ++) {
for (j := 0; j < lgns; j++) {
gj:= g[j];
- if (check_grammar_node_match(toks[lt - i:], gj) == 1) {
+ if (check_grammar_node_match(toks[i:], gj) == 1) {
#sys->print("Something matched !\n");
#gj.print_expr();
#sys->print("Before replace: ");
#print_toks_short(toks);
- gj.callback(gj.ctx, toks[lt-i: lt-i+len gj.expr]);
+ if ((i+len gj.expr) > lt) {
+ continue;
+ }
+ #sys->print("len toks: %d, i: %d, len gj.expr: %d\n", len toks, i, len gj.expr);
+ result := gj.callback(gj.ctx, toks[i:i+len gj.expr]);
if (gj.transform == S_NONE) {
- toks = replace_toks(toks, lt-i, len gj.expr, array[0] of ref TokNode);
+ toks = replace_toks(toks, i, len gj.expr, array[0] of ref TokNode);
+ } else if (gj.transform == nil) {
+ toks = replace_toks(toks, i, len gj.expr, result);
} else {
- toks = replace_toks(toks, lt-i, len gj.expr, array[] of {mk_tok(toks[lt - i].start, toks[lt - i].line, "", gj.transform)});
+ toks = replace_toks(toks, i, len gj.expr, array[] of {mk_tok(toks[i].start, toks[i].line, "", gj.transform)});
}
#sys->print("After replace: ");
changed = 1;
diff --git a/module/sh9parser.m b/module/sh9parser.m
index 22d3f09..aa8a403 100644
--- a/module/sh9parser.m
+++ b/module/sh9parser.m
@@ -33,11 +33,19 @@ ShModule: adt {
name: string;
vars: list of ref ModVar;
procs: list of ref ModProc;
+ find_var: fn(m: self ref ShModule, name: string): ref ModVar;
+ set_var: fn(m: self ref ShModule, v: ref ModVar);
+ print_vars: fn(m: self ref ShModule);
};
ParserCtx: adt {
modules: list of ref ShModule;
add_module: fn(ctx: self ref ParserCtx, name: string);
+ current_module: string;
+ get_current_module: fn(ctx: self ref ParserCtx): ref ShModule;
+ find_var_in_current_module: fn(ctx: self ref ParserCtx, name: string): ref ModVar;
+ find_module: fn(ctx: self ref ParserCtx, name: string): ref ShModule;
+ print_all_vars: fn(ctx: self ref ParserCtx);
};
GrammarNode: adt {