-- Data types for the osh AST. -- They are composed of the builtin ASDL types (string, int, bool) and our -- application type 'id', which is core.id_kind.Id. -- Unimplemented: -- * extended globs: unlike globs, these are parsed up front -- * Brace expansion: should this be another kind of 'word'? It can be -- expanded at compile time. -- * let arithmetic (rarely used) -- * coprocesses module osh { -- A portion of a line, used for error messages. line_span = (int pool_index, int col, int length) -- A primitive token. NOTE: val is redundant with 'loc' for now. If we -- rewrite the parser in C++, we might care for memory footprint. But for -- now this is convenient. -- NOTE: identical strings can shared, if we care. token = (id id, string val, line_span? loc) bracket_op = WholeArray(id op_id) -- * or @ | ArrayIndex(arith_expr expr) suffix_op = StringUnary(id op_id, word arg_word) | PatSub(word pat, word? replace, bool do_all, bool do_prefix, bool do_suffix) -- begin is optional with ${array::1} | Slice(arith_expr? begin, arith_expr? length) array_item = ArrayWord(word w) -- # TODO: make them scoped? array_item::Pair? | ArrayPair(word key, word value) word_part = ArrayLiteralPart(word* words) -- TODO: should be array_item* items | LiteralPart(token token) | EscapedLiteralPart(token token) | SingleQuotedPart(token* tokens) | DoubleQuotedPart(word_part* parts) | VarSubPart(string name, id? prefix_op, -- prefix # or ! operators bracket_op? bracket_op suffix_op? suffix_op) | TildeSubPart(string prefix) | CommandSubPart(command command_list) | ArithSubPart(arith_expr anode) word = TokenWord(token token) | CompoundWord(word_part* parts) lvalue = LeftVar(string name) | LeftIndex(arith_expr obj, arith_expr index) arith_expr = RightVar(string name) -- eval variable | ArithWord(word w) -- a string expression | ArithUnary(id op_id, arith_expr child) | ArithBinary(id op_id, arith_expr left, arith_expr right) | ArithAssign(id op_id, lvalue left, arith_expr right) | TernaryOp(arith_expr cond, arith_expr true_expr, arith_expr false_expr) | FuncCall(arith_expr func, arith_expr* args) bool_expr = WordTest(word w) -- e.g. [[ myword ]] | BoolBinary(id op_id, word left, word right) | BoolUnary(id op_id, word child) | LogicalNot(bool_expr child) | LogicalAnd(bool_expr left, bool_expr right) | LogicalOr(bool_expr left, bool_expr right) -- Notes about here docs: -- * arg_word is the same for here word (<<<) and here doc (<<). -- * arg_word is required, but must be initialized after construction. -- * To reprint the here doc, we need the here_end delimiter, but it doesn't -- matter at runtime. do_expansion is calculated from it. -- * was_filled is only used during th parse and should be eliminated from -- serialization format> redir = Redirect(id op_id, word arg_word, int fd) | HereDoc(id op_id, word? arg_word, int fd, int do_expansion, string here_end, bool was_filled) assign_scope = Global | Local assign_flags = Export | ReadOnly assign_pair = (lvalue lhs, word rhs) env_pair = (string name, word val) -- Homogeneous version command = NoOp | SimpleCommand(word* words, redir* redirects, env_pair* more_env) | Assignment(assign_scope scope, assign_flags* flags, word* words, -- names mentioned without a binding assign_pair* pairs) -- empty redirects for polymorphism? | Fork(command* children) -- shell only allows one command | Pipeline(command* children, bool negated, int* stderr_indices) -- | AndOr(command* children, and_or* ops) | AndOr(command* children, id op_id) -- A command list is used for for/if/while conditions and bodies. No redirects. | CommandList(command* children) -- A brace group is a compound command, with redirects. | BraceGroup(command* children, redir* redirects) | Subshell(command* children, redir* redirects) | DParen(arith_expr child, redir* redirects) | DBracket(bool_expr expr, redir* redirects) -- do_arg_iter: whether to implicitly loop over "$@" | ForEach(string iter_name, word* iter_words, bool do_arg_iter, command* children, redir* redirects) -- C-style for loop. Any of the 3 expressions can be omitted. | ForExpr(arith_expr? init, arith_expr? cond, arith_expr? update, command* children, redir* redirects) | While(command* children, redir* redirects) | Until(command* children, redir* redirects) | If(command* children, redir* redirects) | Case(word to_match, word* pat_word_list, command* children, redir* redirects) | FuncDef(string name, command* children, redir* redirects) and_or = DAmp | DPipe -- For now, using stderr_indices representation because it's more compact. -- |& in osh; |- in oil. -- pipe_op = Pipe | PipeAndStderr }