From a104f80e61f7e6a110a209cf7cc5ffd09d6b5b4f Mon Sep 17 00:00:00 2001 From: "Konstantin Kirik (snegovick)" Date: Sat, 13 Dec 2025 14:45:13 +0300 Subject: Add variable substitution --- appl/cmd/sh92.b | 40 ++++++++++++++++++---- appl/lib/sh9parser.b | 94 ++++++++++++++++++++++++++++++++++++++++++++++++---- module/sh9parser.m | 8 +++++ 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; iprint("%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; iPATH; @@ -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 { -- cgit v1.2.3