aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-09-15 13:48:09 +0000
committer_ov4 <ov4@ov4.org>2026-09-15 13:48:09 +0000
commit165ead4adbf8494db82f7be35c6f8d52ac47ebef (patch)
tree1f5176e3ab097f376c38de2ba2cee7bc1c0d4c6a
parenta6b19b1f4ce89c7daa94f47d7927a0954c0c019e (diff)
add subshell ast
prepare for real subshell and expansion
-rw-r--r--include/lexer/ast.h2
-rw-r--r--module-test/lexer_test.cc23
-rw-r--r--src/lexer/ast.cc20
3 files changed, 42 insertions, 3 deletions
diff --git a/include/lexer/ast.h b/include/lexer/ast.h
index 3434aa3..d4b0fd5 100644
--- a/include/lexer/ast.h
+++ b/include/lexer/ast.h
@@ -20,6 +20,8 @@ public:
string command_text;
size_t left = string::npos;
size_t right = string::npos;
+
+ bool subshell;
};
}
diff --git a/module-test/lexer_test.cc b/module-test/lexer_test.cc
index 623b9ec..364c890 100644
--- a/module-test/lexer_test.cc
+++ b/module-test/lexer_test.cc
@@ -6,7 +6,9 @@ g++ \
src/lexer/token.cc \
src/lexer/ast.cc \
src/lexer/symbol_property.cc \
- -std=c++23 -Iinclude -Ithird_party/magic_enum/include
+ -std=c++23 -Iinclude -Ithird_party/magic_enum/include \
+ -O0 -ggdb3 -fno-omit-frame-pointer -fno-inline -D_GLIBCXX_ASSERTIONS \
+ -o module-test/lexer_test.out
*/
#include <iostream>
@@ -35,7 +37,7 @@ constexpr int MAXLINE = 1024;
int main()
{
verbose = true;
- int test_case = 13;
+ int test_case = 15;
string s;
switch (test_case)
@@ -104,6 +106,16 @@ int main()
s = "alpha&beta";
break;
+ // simple subshell test
+ case 14:
+ s = "alpha && (beta)";
+ break;
+
+ // complex subshell test
+ case 15:
+ s = "alpha && (beta || gamma) && (sleep &)";
+ break;
+
default:
return 0;
}
@@ -138,7 +150,12 @@ int main()
cout << "---------- AST ----------" << endl;
for (size_t i = 0; i < lexer_instance.ast.size(); i++)
{
- print("{}: type: {} left: {} right: {}", i, magic_enum::enum_name(lexer_instance.ast[i].token_type), lexer_instance.ast[i].left, lexer_instance.ast[i].right);
+ print("{}: type: {} left: {} right: {}, subshell {}",
+ i,
+ magic_enum::enum_name(lexer_instance.ast[i].token_type),
+ lexer_instance.ast[i].left,
+ lexer_instance.ast[i].right,
+ lexer_instance.ast[i].subshell ? "TRUE" : "FALSE");
if (lexer_instance.ast[i].token_type == TEXT)
print(" command: {}", lexer_instance.ast[i].command_text);
println();
diff --git a/src/lexer/ast.cc b/src/lexer/ast.cc
index 55b4c42..292728b 100644
--- a/src/lexer/ast.cc
+++ b/src/lexer/ast.cc
@@ -10,6 +10,7 @@
#include "lexer/symbol_property.h"
#include "util/io.h"
#include "error.h"
+#include "magic_enum/magic_enum.hpp"
using namespace std;
@@ -62,6 +63,25 @@ void T_lexer::parse(size_t cmd_begin, size_t cmd_end, size_t ast_vec)
int max_depth = -1;
size_t found_pos = string::npos;
+ // if it's fully inside bracket
+ // then it's subshell
+ loggerln("parse: left token type: {}, right: {}",
+ magic_enum::enum_name(token[cmd_begin].token_type),
+ magic_enum::enum_name(token[cmd_end-1].token_type));
+ if (token[cmd_begin].token_type == LEFT_BRACKET && token[cmd_end-1].token_type == RIGHT_BRACKET)
+ {
+ ast[ast_vec].subshell = true;
+ loggerln("parse: detect subshell {}", ast_vec);
+
+ // eat () subshell token
+ cmd_begin++;
+ cmd_end--;
+ }
+ else
+ {
+ ast[ast_vec].subshell = false;
+ }
+
for (size_t i = cmd_begin; i < cmd_end; i++)
{
if (token[i].bracket_depth > max_depth)