aboutsummaryrefslogtreecommitdiffhomepage
path: root/parse_productions.h
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2013-07-25 15:24:22 -0700
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2013-07-25 15:24:22 -0700
commit4f8d4f378cffa71b4e80bfa2049e2152b429615c (patch)
tree32886a368b1a9ce1917bf7e4316e3a235e629e33 /parse_productions.h
parent3e3eefc2dcb2e0e31b224703a063e05dc8c67996 (diff)
AST no templates
Diffstat (limited to 'parse_productions.h')
-rw-r--r--parse_productions.h647
1 files changed, 647 insertions, 0 deletions
diff --git a/parse_productions.h b/parse_productions.h
new file mode 100644
index 00000000..5ded6af0
--- /dev/null
+++ b/parse_productions.h
@@ -0,0 +1,647 @@
+/**\file parse_tree.h
+
+ Programmatic representation of fish code.
+*/
+
+#ifndef FISH_PARSE_TREE_CONSTRUCTION_H
+#define FISH_PARSE_TREE_CONSTRUCTION_H
+
+#include "parse_tree.h"
+
+/* Terrifying template black magic. */
+
+/*
+
+- Get info for symbol
+- Resolve production from info
+- Get productions for children
+- Get symbols for productions
+
+Production may be:
+
+1. Single value
+2. Sequence of values (possibly empty)
+3. Options of Single / Sequence
+
+Info to specify:
+
+1. Number of different productions
+2. Resolver function
+3. Symbols for associated productions
+
+Choice: should info be a class or a data?
+
+data:
+
+struct Symbol_t
+{
+ enum parse_token_type_t token_type;
+ int (*resolver)(parse_token_type_t tok, parse_keyword_t key); //may be trivial
+ production productions[5];
+}
+
+struct Production_t
+{
+ enum parse_token_type_t symbols[5];
+}
+
+*/
+
+namespace parse_productions
+{
+
+#define MAX_PRODUCTIONS 5
+#define MAX_SYMBOLS_PER_PRODUCTION 5
+
+
+
+struct Production_t
+{
+ enum parse_token_type_t symbols[MAX_SYMBOLS_PER_PRODUCTION];
+};
+
+struct Symbol_t
+{
+ enum parse_token_type_t token_type;
+ int (*resolver)(parse_token_type_t tok, parse_keyword_t key);
+ Production_t productions[MAX_PRODUCTIONS];
+};
+
+
+
+}
+
+namespace parse_symbols
+{
+
+#define SYMBOL(x) static inline parse_token_type_t get_token() { return x; }
+
+#define PRODUCE(X) static int production(parse_token_type_t tok, parse_keyword_t key) { return X; }
+
+#define NO_PRODUCTION (-1)
+
+struct Symbol
+{
+ typedef int magic_symbol_type_t;
+};
+
+template<parse_token_type_t WHICH>
+struct Token : public Symbol
+{
+ SYMBOL(WHICH);
+};
+
+/* Placeholder */
+typedef Token<token_type_invalid> none;
+
+typedef Token<token_type_invalid> EMPTY;
+
+template<typename T0, typename T1, typename T2 = none, typename T3 = none, typename T4 = none, typename T5 = none>
+struct Seq
+{
+ typedef T0 t0;
+ typedef T1 t1;
+ typedef T2 t2;
+ typedef T3 t3;
+ typedef T4 t4;
+ typedef T5 t5;
+
+ typedef int magic_seq_type_t;
+};
+
+template<typename P0, typename P1, typename P2 = none, typename P3 = none, typename P4 = none, typename P5 = none>
+struct OR
+{
+ typedef P0 p0;
+ typedef P1 p1;
+ typedef P2 p2;
+ typedef P3 p3;
+ typedef P4 p4;
+ typedef P5 p5;
+
+ typedef int magic_or_type_t;
+};
+
+template<parse_keyword_t WHICH>
+struct Keyword : public Symbol
+{
+ static inline parse_keyword_t get_token()
+ {
+ return WHICH;
+ }
+};
+
+struct job;
+struct statement;
+struct job_continuation;
+struct boolean_statement;
+struct block_statement;
+struct if_statement;
+struct if_clause;
+struct else_clause;
+struct else_continuation;
+struct switch_statement;
+struct decorated_statement;
+struct switch_statement;
+struct case_item_list;
+struct case_item;
+struct argument_list_nonempty;
+struct argument_list;
+struct block_statement;
+struct block_header;
+struct for_header;
+struct while_header;
+struct begin_header;
+struct function_header;
+struct boolean_statement;
+struct decorated_statement;
+struct plain_statement;
+struct arguments_or_redirections_list;
+struct argument_or_redirection;
+struct redirection;
+struct statement_terminator;
+struct optional_background;
+
+/* A job_list is a list of jobs, separated by semicolons or newlines */
+struct job_list : public Symbol
+{
+ typedef OR<
+ EMPTY,
+ Seq<job, job_list>,
+ Seq<Token<parse_token_type_end>, job_list>
+ > productions;
+
+ SYMBOL(symbol_job_list)
+
+ static int production(parse_token_type_t token_type, parse_keyword_t token_keyword)
+ {
+ switch (token_type)
+ {
+ case parse_token_type_string:
+ // 'end' is special
+ switch (token_keyword)
+ {
+ case parse_keyword_end:
+ case parse_keyword_else:
+ // End this job list
+ return 0;
+
+ default:
+ // Normal string
+ return 1;
+ }
+
+ case parse_token_type_pipe:
+ case parse_token_type_redirection:
+ case parse_token_type_background:
+ return 1;
+
+ case parse_token_type_end:
+ // Empty line
+ return 2;
+
+ case parse_token_type_terminate:
+ // no more commands, just transition to empty
+ return 0;
+ break;
+
+ default:
+ return NO_PRODUCTION;
+ }
+ }
+
+};
+
+/* A job is a non-empty list of statements, separated by pipes. (Non-empty is useful for cases like if statements, where we require a command). To represent "non-empty", we require a statement, followed by a possibly empty job_continuation */
+struct job : public Symbol
+{
+ typedef Seq<statement, job_continuation> sole_production;
+ SYMBOL(symbol_job);
+};
+
+struct job_continuation : public Symbol
+{
+ typedef OR<
+ EMPTY,
+ Seq<Token<parse_token_type_pipe>, statement, job_continuation>
+ > productions;
+
+ SYMBOL(symbol_job_continuation);
+
+ static int production(parse_token_type_t token_type, parse_keyword_t token_keyword)
+ {
+ switch (token_type)
+ {
+ case parse_token_type_pipe:
+ // Pipe, continuation
+ return 1;
+
+ default:
+ // Not a pipe, no job continuation
+ return 0;
+ }
+
+ }
+};
+
+/* A statement is a normal command, or an if / while / and etc */
+struct statement : public Symbol
+{
+ typedef OR<
+ boolean_statement,
+ block_statement,
+ if_statement,
+ switch_statement,
+ decorated_statement
+ > productions;
+
+ SYMBOL(symbol_statement);
+
+ static int production(parse_token_type_t token_type, parse_keyword_t token_keyword)
+ {
+ switch (token_type)
+ {
+ case parse_token_type_string:
+ switch (token_keyword)
+ {
+ case parse_keyword_and:
+ case parse_keyword_or:
+ case parse_keyword_not:
+ return 0;
+
+ case parse_keyword_for:
+ case parse_keyword_while:
+ case parse_keyword_function:
+ case parse_keyword_begin:
+ return 1;
+
+ case parse_keyword_if:
+ return 2;
+
+ case parse_keyword_else:
+ //symbol_stack_pop();
+ return NO_PRODUCTION;
+
+ case parse_keyword_switch:
+ return 3;
+
+ case parse_keyword_end:
+ PARSER_DIE(); //todo
+ return NO_PRODUCTION;
+
+ // 'in' is only special within a for_header
+ case parse_keyword_in:
+ case parse_keyword_none:
+ case parse_keyword_command:
+ case parse_keyword_builtin:
+ case parse_keyword_case:
+ return 4;
+ }
+ break;
+
+ case parse_token_type_pipe:
+ case parse_token_type_redirection:
+ case parse_token_type_background:
+ case parse_token_type_terminate:
+ return NO_PRODUCTION;
+ //parse_error(L"statement", token);
+
+ default:
+ return NO_PRODUCTION;
+ }
+ }
+
+};
+
+struct if_statement : public Symbol
+{
+ typedef Seq<if_clause, else_clause, Keyword<parse_keyword_end>, arguments_or_redirections_list> sole_production;
+ SYMBOL(symbol_if_statement);
+};
+
+struct if_clause : public Symbol
+{
+ typedef Seq<Keyword<parse_keyword_if>, job, statement_terminator, job_list> sole_production;
+ SYMBOL(symbol_if_clause);
+};
+
+struct else_clause : public Symbol
+{
+ typedef OR<
+ EMPTY,
+ Seq<Keyword<parse_keyword_else>, else_continuation>
+ > productions;
+
+ SYMBOL(symbol_else_clause);
+
+ static int production(parse_token_type_t tok, parse_keyword_t key)
+ {
+ switch (key)
+ {
+ case parse_keyword_else:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+};
+
+struct else_continuation : public Symbol
+{
+ typedef OR<
+ Seq<if_clause, else_clause>,
+ Seq<statement_terminator, job_list>
+ > productions;
+
+ SYMBOL(symbol_else_continuation);
+
+ static int production(parse_token_type_t tok, parse_keyword_t key)
+ {
+ switch (key)
+ {
+ case parse_keyword_if:
+ return 0;
+ default:
+ return 1;
+ }
+ }
+};
+
+struct switch_statement : public Symbol
+{
+ typedef Seq<Keyword<parse_keyword_switch>,
+ Token<parse_token_type_string>,
+ statement_terminator,
+ case_item_list,
+ Keyword<parse_keyword_end>
+ > sole_production;
+
+ SYMBOL(symbol_switch_statement);
+};
+
+struct case_item_list : public Symbol
+{
+ typedef OR
+ <
+ EMPTY,
+ Seq<case_item, case_item_list>,
+ Seq<Token<parse_token_type_end>, case_item_list>
+ > productions;
+
+ SYMBOL(symbol_case_item_list);
+
+ static int production(parse_token_type_t tok, parse_keyword_t key)
+ {
+ switch (key)
+ {
+ case parse_keyword_case: return 1;
+
+ default:
+ if (tok == parse_token_type_end)
+ {
+ /* empty line */
+ return 2;
+ }
+ else
+ {
+ return 0;
+ }
+
+ }
+ }
+};
+
+struct case_item : public Symbol
+{
+ typedef Seq<Keyword<parse_keyword_case>, argument_list, statement_terminator, job_list> sole_production;
+
+ SYMBOL(symbol_case_item);
+};
+
+struct argument_list_nonempty : public Symbol
+{
+ typedef Seq<Token<parse_token_type_string>, argument_list> sole_production;
+ SYMBOL(symbol_argument_list_nonempty);
+};
+
+struct argument_list : public Symbol
+{
+ typedef OR<EMPTY, argument_list_nonempty> productions;
+
+ SYMBOL(symbol_argument_list);
+ static int production(parse_token_type_t tok, parse_keyword_t key)
+ {
+ switch (tok)
+ {
+ case parse_token_type_string:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+};
+
+struct block_statement : public Symbol
+{
+ typedef Seq<block_header, statement_terminator, job_list, Keyword<parse_keyword_end>, arguments_or_redirections_list> sole_production;
+
+ SYMBOL(symbol_block_statement);
+};
+
+struct block_header : public Symbol
+{
+ typedef OR<for_header, while_header, function_header, begin_header> productions;
+
+ SYMBOL(symbol_block_header);
+
+ static int production(parse_token_type_t tok, parse_keyword_t key)
+ {
+ switch (key)
+ {
+ // todo
+ case parse_keyword_else:
+ return NO_PRODUCTION;
+ case parse_keyword_for:
+ return 0;
+ case parse_keyword_while:
+ return 1;
+ case parse_keyword_function:
+ return 2;
+ case parse_keyword_begin:
+ return 3;
+ default:
+ return NO_PRODUCTION;
+ }
+ }
+};
+
+struct for_header : public Symbol
+{
+ typedef Seq<Keyword<parse_keyword_for>, Token<parse_token_type_string>, Keyword<parse_keyword_in>, arguments_or_redirections_list> sole_production;
+
+ SYMBOL(symbol_for_header);
+};
+
+struct while_header : public Symbol
+{
+ typedef Seq<Keyword<parse_keyword_while>, statement> sole_production;
+
+ SYMBOL(symbol_while_header);
+};
+
+struct begin_header : public Symbol
+{
+ typedef Keyword<parse_keyword_begin> sole_production;
+ SYMBOL(symbol_begin_header);
+};
+
+struct function_header : public Symbol
+{
+ typedef Seq< Keyword<parse_keyword_function>, Token<parse_token_type_string>, argument_list> sole_production;
+ SYMBOL(symbol_function_header);
+};
+
+/* A boolean statement is AND or OR or NOT */
+struct boolean_statement : public Symbol
+{
+ typedef OR<
+ Seq<Keyword<parse_keyword_and>, statement>,
+ Seq<Keyword<parse_keyword_or>, statement>,
+ Seq<Keyword<parse_keyword_not>, statement>
+ > productions;
+
+ SYMBOL(symbol_boolean_statement);
+
+ static int production(parse_token_type_t tok, parse_keyword_t key)
+ {
+ switch (key)
+ {
+ case parse_keyword_and:
+ return 0;
+ case parse_keyword_or:
+ return 1;
+ case parse_keyword_not:
+ return 2;
+ default:
+ return NO_PRODUCTION;
+ }
+ }
+};
+
+/* A decorated_statement is a command with a list of arguments_or_redirections, possibly with "builtin" or "command" */
+struct decorated_statement : public Symbol
+{
+
+ typedef OR<
+ Seq<Keyword<parse_keyword_command>, plain_statement>,
+ Seq<Keyword<parse_keyword_builtin>, plain_statement>,
+ plain_statement
+ > productions;
+
+ SYMBOL(symbol_decorated_statement);
+
+ static int production(parse_token_type_t tok, parse_keyword_t key)
+ {
+ switch (key)
+ {
+ case parse_keyword_command:
+ return 0;
+ case parse_keyword_builtin:
+ return 1;
+ default:
+ return 2;
+ }
+ }
+};
+
+struct plain_statement : public Symbol
+{
+
+ typedef Seq<Token<parse_token_type_string>, arguments_or_redirections_list, optional_background> sole_production;
+
+ SYMBOL(symbol_plain_statement);
+
+};
+
+struct arguments_or_redirections_list : public Symbol
+{
+ typedef OR<
+ EMPTY,
+ Seq<argument_or_redirection, arguments_or_redirections_list> >
+ productions;
+
+ SYMBOL(symbol_arguments_or_redirections_list);
+
+ static int production(parse_token_type_t tok, parse_keyword_t key)
+ {
+ switch (tok)
+ {
+ case parse_token_type_string:
+ case parse_token_type_redirection:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+};
+
+struct argument_or_redirection : public Symbol
+{
+ typedef OR<
+ Token<parse_token_type_string>,
+ redirection
+ > productions;
+
+
+ SYMBOL(symbol_argument_or_redirection);
+
+ static int production(parse_token_type_t tok, parse_keyword_t key)
+ {
+ switch (tok)
+ {
+ case parse_token_type_string:
+ return 0;
+ case parse_token_type_redirection:
+ return 1;
+ default:
+ return NO_PRODUCTION;
+ }
+ }
+};
+
+struct redirection : public Symbol
+{
+ typedef Token<parse_token_type_redirection> production;
+ SYMBOL(parse_token_type_redirection);
+};
+
+struct statement_terminator : public Symbol
+{
+ typedef Token<parse_token_type_end> production;
+ SYMBOL(parse_token_type_end);
+};
+
+struct optional_background : public Symbol
+{
+ typedef OR<
+ EMPTY,
+ Token<parse_token_type_background>
+ > productions;
+
+ SYMBOL(symbol_optional_background);
+
+ static int production(parse_token_type_t tok, parse_keyword_t key)
+ {
+ switch (tok)
+ {
+ case parse_token_type_background:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+};
+
+}
+
+#endif