|
| 1 | +module Lrama |
| 2 | + class Grammar |
| 3 | + class ParserState |
| 4 | + attr_reader :state_id, :state_list |
| 5 | + |
| 6 | + def initialize(state_id:, state_list:) |
| 7 | + @state_id = state_id |
| 8 | + @state_list = state_list |
| 9 | + end |
| 10 | + |
| 11 | + def enum_definition |
| 12 | + <<~ENUM |
| 13 | + enum #{enum_name} |
| 14 | + { |
| 15 | + #{enum_body} |
| 16 | + }; |
| 17 | + typedef enum #{enum_name} #{enum_type}; |
| 18 | +
|
| 19 | + static const char *const #{enum_name_table_name}[] = { |
| 20 | + #{int_to_name.join(", ")} |
| 21 | + }; |
| 22 | +
|
| 23 | + YY_ATTRIBUTE_UNUSED |
| 24 | + static const char * |
| 25 | + #{enum_name}_name (#{enum_type} num) |
| 26 | + { |
| 27 | + return #{enum_name_table_name}[num]; |
| 28 | + } |
| 29 | +
|
| 30 | + # define #{state_name_macro}(value) #{enum_name}_name (value) |
| 31 | + # define #{current_state_name_macro} #{state_name_macro} (*#{stack_prefix}_p) |
| 32 | + ENUM |
| 33 | + end |
| 34 | + |
| 35 | + def state_name_macro |
| 36 | + "YY_STATE_#{state_name.upcase}_NAME" |
| 37 | + end |
| 38 | + |
| 39 | + def current_state_name_macro |
| 40 | + "YY_CURRENT_STATE_#{state_name.upcase}_NAME" |
| 41 | + end |
| 42 | + |
| 43 | + def states_functions |
| 44 | + <<~FUNC |
| 45 | + # define YYPUSH_STATE_#{state_name.upcase}(value) \\ |
| 46 | + do \\ |
| 47 | + { \\ |
| 48 | + if (#{stack_prefix} + #{states_stack_size_name} - 1 <= #{stack_prefix}_p) \\ |
| 49 | + YYSTATE_STACK_INCREASE (#{stack_prefix}_a, #{stack_prefix}, #{stack_prefix}_p, #{states_stack_size_name}, "#{state_name}"); \\ |
| 50 | + YYDPRINTF ((stderr, "Push %s to #{state_name}\\n", #{state_name_macro} (value))); \\ |
| 51 | + *++#{stack_prefix}_p = value; \\ |
| 52 | + } \\ |
| 53 | + while (0) |
| 54 | +
|
| 55 | + # define YYPOP_STATE_#{state_name.upcase}() \\ |
| 56 | + do \\ |
| 57 | + { \\ |
| 58 | + YYDPRINTF ((stderr, "Pop #{state_name}\\n")); \\ |
| 59 | + if (#{stack_prefix}_p != #{stack_prefix}) \\ |
| 60 | + { \\ |
| 61 | + #{stack_prefix}_p -= 1; \\ |
| 62 | + } \\ |
| 63 | + else \\ |
| 64 | + { \\ |
| 65 | + YYDPRINTF ((stderr, "Try to pop empty #{state_name} stack\\n")); \\ |
| 66 | + } \\ |
| 67 | + } \\ |
| 68 | + while (0) |
| 69 | +
|
| 70 | + # define YYSET_STATE_#{state_name.upcase}(value) \\ |
| 71 | + do \\ |
| 72 | + { \\ |
| 73 | + YYDPRINTF ((stderr, "Set %s to #{state_name}\\n", #{state_name_macro} (value))); \\ |
| 74 | + *#{stack_prefix}_p = value; \\ |
| 75 | + } \\ |
| 76 | + while (0) |
| 77 | +
|
| 78 | + # define YY_STATE_#{state_name.upcase} #{stack_prefix}_p |
| 79 | + FUNC |
| 80 | + end |
| 81 | + |
| 82 | + def states_clean_up_stack |
| 83 | + <<~CODE |
| 84 | + if (#{stack_prefix} != #{stack_prefix}_a) |
| 85 | + YYSTACK_FREE (#{stack_prefix}); |
| 86 | + CODE |
| 87 | + end |
| 88 | + |
| 89 | + def states_stack_size_name |
| 90 | + "#{stack_prefix}_stacksize" |
| 91 | + end |
| 92 | + |
| 93 | + def states_stacks |
| 94 | + <<~STACKS |
| 95 | + /* Current size of state stack size */ |
| 96 | + YYPTRDIFF_T #{states_stack_size_name} = YYINITDEPTH; |
| 97 | +
|
| 98 | + /* The parser state stack (#{stack_prefix}): array, bottom, top. */ |
| 99 | + int #{stack_prefix}_a[YYINITDEPTH]; |
| 100 | + int *#{stack_prefix} = #{stack_prefix}_a; |
| 101 | + int *#{stack_prefix}_p = #{stack_prefix}; |
| 102 | + STACKS |
| 103 | + end |
| 104 | + |
| 105 | + def state_name |
| 106 | + state_id.s_value |
| 107 | + end |
| 108 | + |
| 109 | + def enum_name |
| 110 | + "yyparser_state_#{state_name}" |
| 111 | + end |
| 112 | + |
| 113 | + def enum_type |
| 114 | + "#{enum_name}_t" |
| 115 | + end |
| 116 | + |
| 117 | + def enum_body |
| 118 | + state_list.map do |state| |
| 119 | + state.s_value |
| 120 | + end.join(",\n ") |
| 121 | + end |
| 122 | + |
| 123 | + def int_to_name |
| 124 | + state_list.map do |state| |
| 125 | + "\"#{state.s_value}\"" |
| 126 | + end << "YY_NULLPTR" |
| 127 | + end |
| 128 | + |
| 129 | + def enum_name_table_name |
| 130 | + "#{enum_name}_names" |
| 131 | + end |
| 132 | + |
| 133 | + def stack_prefix |
| 134 | + "yyparser_state_#{state_name}" |
| 135 | + end |
| 136 | + end |
| 137 | + end |
| 138 | +end |
0 commit comments