class Parser
Constants
- SYM_ACCEPT
- SYM_ASTER
- SYM_EMPTY
-
Symbols
- SYM_EOF
- SYM_ERROR
- SYM_EXPR
- SYM_LF
- SYM_LPAREN
- SYM_NUM
- SYM_PLUS
- SYM_PROGRAM
- SYM_RPAREN
- SYM_UNDEF
- YYCHECK
- YYDEFACT
- YYDEFGOTO
- YYFINAL
- YYLAST
- YYNTOKENS
- YYPACT
- YYPACT_NINF
- YYPGOTO
- YYR1
- YYR2
- YYTABLE
- YYTABLE_NINF
Public Class Methods
Source
# File development/compressed_state_table/parser.rb, line 36 def initialize(debug = false) @debug = debug end
Public Instance Methods
Source
# File development/compressed_state_table/parser.rb, line 40 def parse(lexer) state = 0 stack = [] yytoken = SYM_EMPTY parser_action = :push_state next_state = nil rule = nil while true _parser_action = parser_action parser_action = nil case _parser_action when :syntax_error debug_print("Entering :syntax_error") return 1 when :accept debug_print("Entering :accept") return 0 when :push_state # Precondition: `state` is set to new state debug_print("Entering :push_state") debug_print("Push state #{state}") stack.push(state) debug_print("Current stack #{stack}") if state == YYFINAL parser_action = :accept next end parser_action = :decide_parser_action next when :decide_parser_action debug_print("Entering :decide_parser_action") offset = yypact[state] if offset == YYPACT_NINF parser_action = :yydefault next end # Ensure next token if yytoken == SYM_EMPTY debug_print("Reading a token") yytoken = lexer.next_token end case yytoken when SYM_EOF debug_print("Now at end of input.") when SYM_ERROR parser_action = :syntax_error next else debug_print("Next token is #{yytoken}") end idx = offset + yytoken if idx < 0 || YYLAST < idx debug_print("Decide next parser action as :yydefault") parser_action = :yydefault next end if yycheck[idx] != yytoken debug_print("Decide next parser action as :yydefault") parser_action = :yydefault next end action = yytable[idx] if action == YYTABLE_NINF parser_action = :syntax_error next end if action > 0 # Shift debug_print("Decide next parser action as :yyshift") next_state = action parser_action = :yyshift next else # Reduce debug_print("Decide next parser action as :yyreduce") rule = -action parser_action = :yyreduce next end when :yyshift # Precondition: `next_state` is set debug_print("Entering :yyshift") raise "next_state is not set" unless next_state yytoken = SYM_EMPTY state = next_state next_state = nil parser_action = :push_state next when :yydefault debug_print("Entering :yydefault") rule = yydefact[state] if rule == 0 parser_action = :syntax_error next end parser_action = :yyreduce next when :yyreduce # Precondition: `rule`, used for reduce, is set debug_print("Entering :yyreduce") raise "rule is not set" unless rule rhs_length = yyr2[rule] lhs_nterm = yyr1[rule] lhs_nterm_id = lhs_nterm - YYNTOKENS text = "Execute action for Rule (#{rule}) " case rule when 1 text << "$accept: program \"end of file\"" when 2 text << "program: ε" when 3 text << "program: expr LF" when 4 text << "expr: NUM" when 5 text << "expr: expr '+' expr" when 6 text << "expr: expr '*' expr" when 7 text << "expr: '(' expr ')'" end debug_print(text) debug_print("Pop #{rhs_length} elements") debug_print("Stack before pop: #{stack}") stack.pop(rhs_length) debug_print("Stack after pop: #{stack}") state = stack[-1] # "Shift" LHS nonterminal offset = yypgoto[lhs_nterm_id] if offset == YYPACT_NINF state = yydefgoto[lhs_nterm_id] else idx = offset + state if idx < 0 || YYLAST < idx state = yydefgoto[lhs_nterm_id] elsif yycheck[idx] != state state = yydefgoto[lhs_nterm_id] else state = yytable[idx] end end rule = nil parser_action = :push_state next else raise "Unknown parser_action: #{parser_action}" end end end