From a44f4cb75376c015c5b9fe0806786a0abfc044c8 Mon Sep 17 00:00:00 2001 From: Junichi Kobayashi Date: Thu, 19 Oct 2023 21:47:41 +0900 Subject: [PATCH 1/2] Remove hand-made parser --- lib/lrama.rb | 2 +- lib/lrama/parser.rb | 293 ------ lib/lrama/parser/token_scanner.rb | 56 -- spec/lrama/parser_spec.rb | 1461 ----------------------------- spec/spec_helper.rb | 2 +- 5 files changed, 2 insertions(+), 1812 deletions(-) delete mode 100644 lib/lrama/parser.rb delete mode 100644 lib/lrama/parser/token_scanner.rb delete mode 100644 spec/lrama/parser_spec.rb diff --git a/lib/lrama.rb b/lib/lrama.rb index 01b1c97d..aa813a52 100644 --- a/lib/lrama.rb +++ b/lib/lrama.rb @@ -8,7 +8,7 @@ require "lrama/option_parser" require "lrama/options" require "lrama/output" -require "lrama/parser" +# require "lrama/parser" require "lrama/report" require "lrama/state" require "lrama/states" diff --git a/lib/lrama/parser.rb b/lib/lrama/parser.rb deleted file mode 100644 index 18e2ef03..00000000 --- a/lib/lrama/parser.rb +++ /dev/null @@ -1,293 +0,0 @@ -require "lrama/report/duration" -require "lrama/parser/token_scanner" - -module Lrama - # Parser for parse.y, generates a grammar - class Parser - include Lrama::Report::Duration - - T = Lrama::Lexer::Token - - def initialize(text) - @text = text - end - - def parse - report_duration(:parse) do - lexer = Lexer.new(@text) - grammar = Grammar.new - process_prologue(grammar, lexer) - parse_bison_declarations(TokenScanner.new(lexer.bison_declarations_tokens), grammar) - parse_grammar_rules(TokenScanner.new(lexer.grammar_rules_tokens), grammar) - process_epilogue(grammar, lexer) - grammar.prepare - grammar.compute_nullable - grammar.compute_first_set - grammar.validate! - - grammar - end - end - - private - - def process_prologue(grammar, lexer) - grammar.prologue_first_lineno = lexer.prologue.first[1] if lexer.prologue.first - grammar.prologue = lexer.prologue.map(&:first).join - end - - def process_epilogue(grammar, lexer) - grammar.epilogue_first_lineno = lexer.epilogue.first[1] if lexer.epilogue.first - grammar.epilogue = lexer.epilogue.map(&:first).join - end - - def parse_bison_declarations(ts, grammar) - precedence_number = 0 - - while !ts.eots? do - case ts.current_type - when T::P_expect - ts.next - grammar.expect = ts.consume!(T::Number).s_value - when T::P_define - ts.next - # Ignore - ts.consume_multi(T::Ident) - when T::P_printer - lineno = ts.current_token.line - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:printer, code) - ident_or_tags = ts.consume_multi(T::Ident, T::Tag) - grammar.add_printer(ident_or_tags: ident_or_tags, code: code, lineno: lineno) - when T::P_error_token - lineno = ts.current_token.line - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:printer, code) - ident_or_tags = ts.consume_multi(T::Ident, T::Tag) - grammar.add_error_token(ident_or_tags: ident_or_tags, code: code, lineno: lineno) - when T::P_lex_param - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:lex_param, code) - grammar.lex_param = code.token_code.s_value - when T::P_parse_param - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:parse_param, code) - grammar.parse_param = code.token_code.s_value - when T::P_initial_action - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:initial_action, code) - ts.consume(T::Semicolon) - grammar.initial_action = code - when T::P_union - lineno = ts.current_token.line - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:union, code) - ts.consume(T::Semicolon) - grammar.set_union(code, lineno) - when T::P_token - # %token tag? (ident number? string?)+ - # - # * ident can be char, e.g. '\\', '\t', '\13' - # * number is a token_id for term - # - # These are valid token declaration (from CRuby parse.y) - # - # %token END_OF_INPUT 0 "end-of-input" - # %token '\\' "backslash" - # %token tSP "escaped space" - # %token tUPLUS 132 "unary+" - # %token tCOLON3 ":: at EXPR_BEG" - # %token tSTRING_DBEG tSTRING_DVAR tLAMBEG tLABEL_END - # - # - # See: https://www.gnu.org/software/bison/manual/html_node/Symbol-Decls.html - ts.next - opt_tag = ts.consume(T::Tag) - - while (id = ts.consume(T::Ident, T::Char)) do - opt_number = ts.consume(T::Number) - opt_string = ts.consume(T::String) - # Can replace 0 (EOF) - grammar.add_term( - id: id, - alias_name: opt_string && opt_string.s_value, - token_id: opt_number && opt_number.s_value, - tag: opt_tag, - replace: true, - ) - end - when T::P_type - # %type tag? (ident|char|string)+ - # - # See: https://www.gnu.org/software/bison/manual/html_node/Symbol-Decls.html - ts.next - opt_tag = ts.consume(T::Tag) - - while (id = ts.consume(T::Ident, T::Char, T::String)) do - grammar.add_type( - id: id, - tag: opt_tag - ) - end - when T::P_nonassoc - # %nonassoc (ident|char|string)+ - ts.next - while (id = ts.consume(T::Ident, T::Char, T::String)) do - sym = grammar.add_term(id: id) - grammar.add_nonassoc(sym, precedence_number) - end - precedence_number += 1 - when T::P_left - # %left (ident|char|string)+ - ts.next - while (id = ts.consume(T::Ident, T::Char, T::String)) do - sym = grammar.add_term(id: id) - grammar.add_left(sym, precedence_number) - end - precedence_number += 1 - when T::P_right - # %right (ident|char|string)+ - ts.next - while (id = ts.consume(T::Ident, T::Char, T::String)) do - sym = grammar.add_term(id: id) - grammar.add_right(sym, precedence_number) - end - precedence_number += 1 - when T::P_precedence - # %precedence (ident|char|string)+ - ts.next - while (id = ts.consume(T::Ident, T::Char, T::String)) do - sym = grammar.add_term(id: id) - grammar.add_precedence(sym, precedence_number) - end - precedence_number += 1 - when nil - # end of input - raise "Reach to end of input within declarations" - else - raise "Unexpected token: #{ts.current_token}" - end - end - end - - def parse_grammar_rules(ts, grammar) - while !ts.eots? do - parse_grammar_rule(ts, grammar) - end - end - - # TODO: Take care of %prec of rule. - # If %prec exists, user code before %prec - # is NOT an action. For example "{ code 3 }" is NOT an action. - # - # keyword_class { code 2 } tSTRING '!' keyword_end { code 3 } %prec "=" - def parse_grammar_rule(ts, grammar) - # LHS - lhs = ts.consume!(T::Ident_Colon) # class: - lhs.type = T::Ident - if named_ref = ts.consume(T::Named_Ref) - lhs.alias = named_ref.s_value - end - - rhs = parse_grammar_rule_rhs(ts, grammar, lhs) - - grammar.add_rule(lhs: lhs, rhs: rhs, lineno: rhs.first ? rhs.first.line : lhs.line) - - while true do - case ts.current_type - when T::Bar - # | - bar_lineno = ts.current_token.line - ts.next - rhs = parse_grammar_rule_rhs(ts, grammar, lhs) - grammar.add_rule(lhs: lhs, rhs: rhs, lineno: rhs.first ? rhs.first.line : bar_lineno) - when T::Semicolon - # ; - ts.next - break - when T::Ident_Colon - # Next lhs can be here because ";" is optional. - # Do not consume next token. - break - when nil - # end of input can be here when ";" is omitted - break - else - raise "Unexpected token: #{ts.current_token}" - end - end - end - - def parse_grammar_rule_rhs(ts, grammar, lhs) - a = [] - prec_seen = false - code_after_prec = false - - while true do - # TODO: String can be here - case ts.current_type - when T::Ident - # keyword_class - - raise "Ident after %prec" if prec_seen - a << ts.current_token - ts.next - when T::Char - # '!' - - raise "Char after %prec" if prec_seen - a << ts.current_token - ts.next - when T::P_prec - # %prec tPLUS - # - # See: https://www.gnu.org/software/bison/manual/html_node/Contextual-Precedence.html - - ts.next - prec_seen = true - precedence_id = ts.consume!(T::Ident, T::String, T::Char) - precedence_sym = grammar.find_symbol_by_id!(precedence_id) - a << precedence_sym - when T::User_code - # { code } in the middle of rhs - - if prec_seen - raise "Multiple User_code after %prec" if code_after_prec - code_after_prec = true - end - - code = ts.current_token - code.numberize_references(lhs, a) - grammar.build_references(code) - a << code - ts.next - when T::Named_Ref - ts.previous_token.alias = ts.current_token.s_value - ts.next - when T::Bar - # | - break - when T::Semicolon - # ; - break - when T::Ident_Colon - # Next lhs can be here because ";" is optional. - break - when nil - # end of input can be here when ";" is omitted - break - else - raise "Unexpected token: #{ts.current_token}" - end - end - - return a - end - end -end diff --git a/lib/lrama/parser/token_scanner.rb b/lib/lrama/parser/token_scanner.rb deleted file mode 100644 index 992b5742..00000000 --- a/lib/lrama/parser/token_scanner.rb +++ /dev/null @@ -1,56 +0,0 @@ -module Lrama - class Parser - class TokenScanner - def initialize(tokens) - @tokens = tokens - @index = 0 - end - - def current_token - @tokens[@index] - end - - def current_type - current_token&.type - end - - def previous_token - @tokens[@index - 1] - end - - def next - token = current_token - @index += 1 - return token - end - - def consume(*token_types) - if token_types.include?(current_type) - return self.next - end - - return nil - end - - def consume!(*token_types) - consume(*token_types) || (raise "#{token_types} is expected but #{current_type}. #{current_token}") - end - - def consume_multi(*token_types) - a = [] - - while token_types.include?(current_type) - a << self.next - end - - raise "No token is consumed. #{token_types}" if a.empty? - - return a - end - - def eots? - current_token.nil? - end - end - end -end diff --git a/spec/lrama/parser_spec.rb b/spec/lrama/parser_spec.rb deleted file mode 100644 index 6bae8ace..00000000 --- a/spec/lrama/parser_spec.rb +++ /dev/null @@ -1,1461 +0,0 @@ -RSpec.describe Lrama::Parser do - T ||= Lrama::Lexer::Token - Type = Lrama::Type - Sym = Lrama::Grammar::Symbol - Precedence = Lrama::Grammar::Precedence - Rule = Lrama::Grammar::Rule - Printer = Lrama::Grammar::Printer - Code = Lrama::Grammar::Code - - let(:header) do - <<~HEADER -%{ -// Prologue -%} - -%union { - int i; - long l; - char *str; -} - -%token EOI 0 "EOI" -%token keyword_class -%token tNUMBER -%token tSTRING -%token keyword_end "end" -%token tPLUS "+" -%token tMINUS "-" -%token tEQ "=" -%token tEQEQ "==" - -%type class /* comment for class */ - -%nonassoc tEQEQ -%left tPLUS tMINUS -%right tEQ - - HEADER - end - - describe '#parse' do - it "basic" do - y = File.read(fixture_path("common/basic.y")) - grammar = Lrama::Parser.new(y).parse - - expect(grammar.union.code.s_value).to eq(<<-CODE.chomp) - - int i; - long l; - char *str; - - CODE - - expect(grammar.expect).to eq(0) - expect(grammar.printers).to eq([ - Printer.new( - ident_or_tags: [T.new(type: T::Tag, s_value: "")], - code: Code.new(type: :printer, token_code: T.new(type: T::User_code, s_value: "\n print_int();\n")), - lineno: 15 - ), - Printer.new( - ident_or_tags: [T.new(type: T::Ident, s_value: "tNUMBER"), T.new(type: T::Ident, s_value: "tSTRING")], - code: Code.new(type: :printer, token_code: T.new(type: T::User_code, s_value: "\n print_token();\n")), - lineno: 18 - ), - ]) - expect(grammar.lex_param).to eq("struct lex_params *p") - expect(grammar.parse_param).to eq("struct parse_params *p") - expect(grammar.initial_action).to eq(Code.new(type: :initial_action, token_code: T.new(type: T::User_code, s_value: "\n initial_action_func(@$);\n"))) - expect(grammar.symbols.sort_by(&:number)).to eq([ - Sym.new(id: T.new(type: T::Ident, s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "YYerror"), alias_name: "error", number: 1, tag: nil, term: true, token_id: 256, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "YYUNDEF"), alias_name: "\"invalid token\"", number: 2, tag: nil, term: true, token_id: 257, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Char, s_value: "'\\\\'"), alias_name: "\"backslash\"", number: 3, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 92, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Char, s_value: "'\\13'"), alias_name: "\"escaped vertical tab\"", number: 4, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 11, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "keyword_class"), alias_name: nil, number: 5, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 258, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "keyword_class2"), alias_name: nil, number: 6, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 259, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "tNUMBER"), alias_name: nil, number: 7, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 260, nullable: false, precedence: nil, printer: grammar.printers[1]), - Sym.new(id: T.new(type: T::Ident, s_value: "tSTRING"), alias_name: nil, number: 8, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 261, nullable: false, precedence: nil, printer: grammar.printers[1]), - Sym.new(id: T.new(type: T::Ident, s_value: "keyword_end"), alias_name: "\"end\"", number: 9, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 262, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "tPLUS"), alias_name: "\"+\"", number: 10, tag: nil, term: true, token_id: 263, nullable: false, precedence: Precedence.new(type: :left, precedence: 1), printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "tMINUS"), alias_name: "\"-\"", number: 11, tag: nil, term: true, token_id: 264, nullable: false, precedence: Precedence.new(type: :left, precedence: 1), printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "tEQ"), alias_name: "\"=\"", number: 12, tag: nil, term: true, token_id: 265, nullable: false, precedence: Precedence.new(type: :right, precedence: 2), printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "tEQEQ"), alias_name: "\"==\"", number: 13, tag: nil, term: true, token_id: 266, nullable: false, precedence: Precedence.new(type: :nonassoc, precedence: 0), printer: nil), - Sym.new(id: T.new(type: T::Char, s_value: "'>'"), alias_name: nil, number: 14, tag: nil, term: true, token_id: 62, nullable: false, precedence: Precedence.new(type: :left, precedence: 1), printer: nil), - Sym.new(id: T.new(type: T::Char, s_value: "'+'"), alias_name: nil, number: 15, tag: nil, term: true, token_id: 43, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Char, s_value: "'-'"), alias_name: nil, number: 16, tag: nil, term: true, token_id: 45, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Char, s_value: "'!'"), alias_name: nil, number: 17, tag: nil, term: true, token_id: 33, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Char, s_value: "'?'"), alias_name: nil, number: 18, tag: nil, term: true, token_id: 63, nullable: false, precedence: nil, printer: nil), - - Sym.new(id: T.new(type: T::Ident, s_value: "$accept"), alias_name: nil, number: 19, tag: nil, term: false, token_id: 0, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "program"), alias_name: nil, number: 20, tag: nil, term: false, token_id: 1, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "class"), alias_name: nil, number: 21, tag: T.new(type: T::Tag, s_value: ""), term: false, token_id: 2, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "$@1"), alias_name: nil, number: 22, tag: nil, term: false, token_id: 3, nullable: true, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "$@2"), alias_name: nil, number: 23, tag: nil, term: false, token_id: 4, nullable: true, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "$@3"), alias_name: nil, number: 24, tag: nil, term: false, token_id: 5, nullable: true, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "$@4"), alias_name: nil, number: 25, tag: nil, term: false, token_id: 6, nullable: true, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "strings_1"), alias_name: nil, number: 26, tag: nil, term: false, token_id: 7, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "strings_2"), alias_name: nil, number: 27, tag: nil, term: false, token_id: 8, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "string_1"), alias_name: nil, number: 28, tag: nil, term: false, token_id: 9, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "string_2"), alias_name: nil, number: 29, tag: nil, term: false, token_id: 10, nullable: false, precedence: nil, printer: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "string"), alias_name: nil, number: 30, tag: nil, term: false, token_id: 11, nullable: false, precedence: nil, printer: nil), - ]) - expect(grammar.types).to eq([Type.new(id: T.new(type: T::Ident, s_value: "class"), tag: T.new(type: T::Tag, s_value: ""))]) - expect(grammar._rules).to eq([ - [ - T.new(type: T::Ident, s_value: "program"), - [ - T.new(type: T::Ident, s_value: "class"), - ], - 57, - ], - [ - T.new(type: T::Ident, s_value: "program"), - [ - T.new(type: T::Char, s_value: "'+'"), - T.new(type: T::Ident, s_value: "strings_1"), - ], - 58, - ], - [ - T.new(type: T::Ident, s_value: "program"), - [ - T.new(type: T::Char, s_value: "'-'"), - T.new(type: T::Ident, s_value: "strings_2"), - ], - 59, - ], - [ - T.new(type: T::Ident, s_value: "class"), - [ - T.new(type: T::Ident, s_value: "keyword_class"), - T.new(type: T::Ident, s_value: "tSTRING"), - T.new(type: T::Ident, s_value: "keyword_end"), - grammar.find_symbol_by_s_value!("tPLUS"), - T.new(type: T::User_code, s_value: " code 1 "), - ], - 62, - ], - [ - T.new(type: T::Ident, s_value: "class"), - [ - T.new(type: T::Ident, s_value: "keyword_class"), - T.new(type: T::User_code, s_value: " code 2 "), - T.new(type: T::Ident, s_value: "tSTRING"), - T.new(type: T::Char, s_value: "'!'"), - T.new(type: T::Ident, s_value: "keyword_end"), - T.new(type: T::User_code, s_value: " code 3 "), - grammar.find_symbol_by_s_value!("tEQ"), - ], - 64, - ], - [ - T.new(type: T::Ident, s_value: "class"), - [ - T.new(type: T::Ident, s_value: "keyword_class"), - T.new(type: T::User_code, s_value: " code 4 "), - T.new(type: T::Ident, s_value: "tSTRING"), - T.new(type: T::Char, s_value: "'?'"), - T.new(type: T::Ident, s_value: "keyword_end"), - T.new(type: T::User_code, s_value: " code 5 "), - grammar.find_symbol_by_s_value!("'>'"), - ], - 65, - ], - [ - T.new(type: T::Ident, s_value: "strings_1"), - [ - T.new(type: T::Ident, s_value: "string_1"), - ], - 68, - ], - [ - T.new(type: T::Ident, s_value: "strings_2"), - [ - T.new(type: T::Ident, s_value: "string_1"), - ], - 71, - ], - [ - T.new(type: T::Ident, s_value: "strings_2"), - [ - T.new(type: T::Ident, s_value: "string_2"), - ], - 72, - ], - [ - T.new(type: T::Ident, s_value: "string_1"), - [ - T.new(type: T::Ident, s_value: "string"), - ], - 75, - ], - [ - T.new(type: T::Ident, s_value: "string_2"), - [ - T.new(type: T::Ident, s_value: "string"), - T.new(type: T::Char, s_value: "'+'"), - ], - 78, - ], - [ - T.new(type: T::Ident, s_value: "string"), - [ - T.new(type: T::Ident, s_value: "tSTRING") - ], - 81, - ], - ]) - expect(grammar.rules).to eq([ - Rule.new( - id: 0, - lhs: grammar.find_symbol_by_s_value!("$accept"), - rhs: [ - grammar.find_symbol_by_s_value!("program"), - grammar.find_symbol_by_s_value!("EOI"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("EOI"), - lineno: 57, - ), - Rule.new( - id: 1, - lhs: grammar.find_symbol_by_s_value!("program"), - rhs: [ - grammar.find_symbol_by_s_value!("class"), - ], - code: nil, - nullable: false, - precedence_sym: nil, - lineno: 57, - ), - Rule.new( - id: 2, - lhs: grammar.find_symbol_by_s_value!("program"), - rhs: [ - grammar.find_symbol_by_s_value!("'+'"), - grammar.find_symbol_by_s_value!("strings_1"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("'+'"), - lineno: 58, - ), - Rule.new( - id: 3, - lhs: grammar.find_symbol_by_s_value!("program"), - rhs: [ - grammar.find_symbol_by_s_value!("'-'"), - grammar.find_symbol_by_s_value!("strings_2"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("'-'"), - lineno: 59, - ), - Rule.new( - id: 4, - lhs: grammar.find_symbol_by_s_value!("class"), - rhs: [ - grammar.find_symbol_by_s_value!("keyword_class"), - grammar.find_symbol_by_s_value!("tSTRING"), - grammar.find_symbol_by_s_value!("keyword_end"), - ], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " code 1 ")), - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("tPLUS"), - lineno: 62, - ), - Rule.new( - id: 5, - lhs: grammar.find_symbol_by_s_value!("$@1"), - rhs: [], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " code 2 ")), - nullable: true, - precedence_sym: nil, - lineno: 64, - ), - Rule.new( - id: 6, - lhs: grammar.find_symbol_by_s_value!("$@2"), - rhs: [], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " code 3 ")), - nullable: true, - precedence_sym: nil, - lineno: 64, - ), - Rule.new( - id: 7, - lhs: grammar.find_symbol_by_s_value!("class"), - rhs: [ - grammar.find_symbol_by_s_value!("keyword_class"), - grammar.find_symbol_by_s_value!("$@1"), - grammar.find_symbol_by_s_value!("tSTRING"), - grammar.find_symbol_by_s_value!("'!'"), - grammar.find_symbol_by_s_value!("keyword_end"), - grammar.find_symbol_by_s_value!("$@2"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("tEQ"), - lineno: 64, - ), - Rule.new( - id: 8, - lhs: grammar.find_symbol_by_s_value!("$@3"), - rhs: [], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " code 4 ")), - nullable: true, - precedence_sym: nil, - lineno: 65, - ), - Rule.new( - id: 9, - lhs: grammar.find_symbol_by_s_value!("$@4"), - rhs: [], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " code 5 ")), - nullable: true, - precedence_sym: nil, - lineno: 65, - ), - Rule.new( - id: 10, - lhs: grammar.find_symbol_by_s_value!("class"), - rhs: [ - grammar.find_symbol_by_s_value!("keyword_class"), - grammar.find_symbol_by_s_value!("$@3"), - grammar.find_symbol_by_s_value!("tSTRING"), - grammar.find_symbol_by_s_value!("'?'"), - grammar.find_symbol_by_s_value!("keyword_end"), - grammar.find_symbol_by_s_value!("$@4"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("'>'"), - lineno: 65, - ), - Rule.new( - id: 11, - lhs: grammar.find_symbol_by_s_value!("strings_1"), - rhs: [ - grammar.find_symbol_by_s_value!("string_1"), - ], - code: nil, - nullable: false, - precedence_sym: nil, - lineno: 68, - ), - Rule.new( - id: 12, - lhs: grammar.find_symbol_by_s_value!("strings_2"), - rhs: [ - grammar.find_symbol_by_s_value!("string_1"), - ], - code: nil, - nullable: false, - precedence_sym: nil, - lineno: 71, - ), - Rule.new( - id: 13, - lhs: grammar.find_symbol_by_s_value!("strings_2"), - rhs: [ - grammar.find_symbol_by_s_value!("string_2"), - ], - code: nil, - nullable: false, - precedence_sym: nil, - lineno: 72, - ), - Rule.new( - id: 14, - lhs: grammar.find_symbol_by_s_value!("string_1"), - rhs: [ - grammar.find_symbol_by_s_value!("string"), - ], - code: nil, - nullable: false, - precedence_sym: nil, - lineno: 75, - ), - Rule.new( - id: 15, - lhs: grammar.find_symbol_by_s_value!("string_2"), - rhs: [ - grammar.find_symbol_by_s_value!("string"), - grammar.find_symbol_by_s_value!("'+'"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("'+'"), - lineno: 78, - ), - Rule.new( - id: 16, - lhs: grammar.find_symbol_by_s_value!("string"), - rhs: [ - grammar.find_symbol_by_s_value!("tSTRING"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("tSTRING"), - lineno: 81, - ), - ]) - end - - it "nullable" do - y = File.read(fixture_path("common/nullable.y")) - grammar = Lrama::Parser.new(y).parse - - expect(grammar.nterms.sort_by(&:number)).to eq([ - Sym.new(id: T.new(type: T::Ident, s_value: "$accept"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 0, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "program"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 1, nullable: true), - Sym.new(id: T.new(type: T::Ident, s_value: "stmt"), alias_name: nil, number: 8, tag: nil, term: false, token_id: 2, nullable: true), - Sym.new(id: T.new(type: T::Ident, s_value: "expr"), alias_name: nil, number: 9, tag: nil, term: false, token_id: 3, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "opt_expr"), alias_name: nil, number: 10, tag: nil, term: false, token_id: 4, nullable: true), - Sym.new(id: T.new(type: T::Ident, s_value: "opt_semicolon"), alias_name: nil, number: 11, tag: nil, term: false, token_id: 5, nullable: true), - Sym.new(id: T.new(type: T::Ident, s_value: "opt_colon"), alias_name: nil, number: 12, tag: nil, term: false, token_id: 6, nullable: true), - ]) - expect(grammar.rules).to eq([ - Rule.new( - id: 0, - lhs: grammar.find_symbol_by_s_value!("$accept"), - rhs: [ - grammar.find_symbol_by_s_value!("program"), - grammar.find_symbol_by_s_value!("YYEOF"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("YYEOF"), - lineno: 15, - ), - Rule.new( - id: 1, - lhs: grammar.find_symbol_by_s_value!("program"), - rhs: [ - grammar.find_symbol_by_s_value!("stmt"), - ], - code: nil, - nullable: true, - precedence_sym: nil, - lineno: 15, - ), - Rule.new( - id: 2, - lhs: grammar.find_symbol_by_s_value!("stmt"), - rhs: [ - grammar.find_symbol_by_s_value!("expr"), - grammar.find_symbol_by_s_value!("opt_semicolon"), - ], - code: nil, - nullable: false, - precedence_sym: nil, - lineno: 17, - ), - Rule.new( - id: 3, - lhs: grammar.find_symbol_by_s_value!("stmt"), - rhs: [ - grammar.find_symbol_by_s_value!("opt_expr"), - grammar.find_symbol_by_s_value!("opt_colon"), - ], - code: nil, - nullable: true, - precedence_sym: nil, - lineno: 18, - ), - Rule.new( - id: 4, - lhs: grammar.find_symbol_by_s_value!("stmt"), - rhs: [], - code: nil, - nullable: true, - precedence_sym: nil, - lineno: 19, - ), - Rule.new( - id: 5, - lhs: grammar.find_symbol_by_s_value!("expr"), - rhs: [ - grammar.find_symbol_by_s_value!("tNUMBER"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("tNUMBER"), - lineno: 22, - ), - Rule.new( - id: 6, - lhs: grammar.find_symbol_by_s_value!("opt_expr"), - rhs: [], - code: nil, - nullable: true, - precedence_sym: nil, - lineno: 24, - ), - Rule.new( - id: 7, - lhs: grammar.find_symbol_by_s_value!("opt_expr"), - rhs: [ - grammar.find_symbol_by_s_value!("expr"), - ], - code: nil, - nullable: false, - precedence_sym: nil, - lineno: 25, - ), - Rule.new( - id: 8, - lhs: grammar.find_symbol_by_s_value!("opt_semicolon"), - rhs: [], - code: nil, - nullable: true, - precedence_sym: nil, - lineno: 28, - ), - Rule.new( - id: 9, - lhs: grammar.find_symbol_by_s_value!("opt_semicolon"), - rhs: [ - grammar.find_symbol_by_s_value!("';'"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("';'"), - lineno: 29, - ), - Rule.new( - id: 10, - lhs: grammar.find_symbol_by_s_value!("opt_colon"), - rhs: [], - code: nil, - nullable: true, - precedence_sym: nil, - lineno: 32, - ), - Rule.new( - id: 11, - lhs: grammar.find_symbol_by_s_value!("opt_colon"), - rhs: [ - grammar.find_symbol_by_s_value!("'.'"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("'.'"), - lineno: 33, - ), - ]) - end - - it "; for rules is optional" do - y = header + <<~INPUT -%% - -program: class - -class : keyword_class tSTRING keyword_end { code 1 } - | error - -%% - INPUT - - grammar = Lrama::Parser.new(y).parse - - expect(grammar._rules).to eq([ - [ - T.new(type: T::Ident, s_value: "program"), - [ - T.new(type: T::Ident, s_value: "class") - ], - 29, - ], - [ - T.new(type: T::Ident, s_value: "class"), - [ - T.new(type: T::Ident, s_value: "keyword_class"), - T.new(type: T::Ident, s_value: "tSTRING"), - T.new(type: T::Ident, s_value: "keyword_end"), - T.new(type: T::User_code, s_value: " code 1 "), - ], - 31, - ], - [ - T.new(type: T::Ident, s_value: "class"), - [ - T.new(type: T::Ident, s_value: "error") - ], - 32, - ], - ]) - end - - it "error token" do - y = header + <<~INPUT -%% - -program: class ; - -class : keyword_class tSTRING keyword_end { code 1 } - | error - ; - -%% - - INPUT - grammar = Lrama::Parser.new(y).parse - - expect(grammar.terms.sort_by(&:number)).to eq([ - Sym.new(id: T.new(type: T::Ident, s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "YYerror"), alias_name: "error", number: 1, tag: nil, term: true, token_id: 256, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "YYUNDEF"), alias_name: "\"invalid token\"", number: 2, tag: nil, term: true, token_id: 257, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "keyword_class"), alias_name: nil, number: 3, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 258, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "tNUMBER"), alias_name: nil, number: 4, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 259, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "tSTRING"), alias_name: nil, number: 5, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 260, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "keyword_end"), alias_name: "\"end\"", number: 6, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 261, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "tPLUS"), alias_name: "\"+\"", number: 7, tag: nil, term: true, token_id: 262, nullable: false, precedence: Precedence.new(type: :left, precedence: 1)), - Sym.new(id: T.new(type: T::Ident, s_value: "tMINUS"), alias_name: "\"-\"", number: 8, tag: nil, term: true, token_id: 263, nullable: false, precedence: Precedence.new(type: :left, precedence: 1)), - Sym.new(id: T.new(type: T::Ident, s_value: "tEQ"), alias_name: "\"=\"", number: 9, tag: nil, term: true, token_id: 264, nullable: false, precedence: Precedence.new(type: :right, precedence: 2)), - Sym.new(id: T.new(type: T::Ident, s_value: "tEQEQ"), alias_name: "\"==\"", number: 10, tag: nil, term: true, token_id: 265, nullable: false, precedence: Precedence.new(type: :nonassoc, precedence: 0)), - ]) - expect(grammar._rules).to eq([ - [ - T.new(type: T::Ident, s_value: "program"), - [ - T.new(type: T::Ident, s_value: "class") - ], - 29, - ], - [ - T.new(type: T::Ident, s_value: "class"), - [ - T.new(type: T::Ident, s_value: "keyword_class"), - T.new(type: T::Ident, s_value: "tSTRING"), - T.new(type: T::Ident, s_value: "keyword_end"), - T.new(type: T::User_code, s_value: " code 1 "), - ], - 31, - ], - [ - T.new(type: T::Ident, s_value: "class"), - [ - T.new(type: T::Ident, s_value: "error") - ], - 32, - ], - ]) - end - - it "action in the middle of RHS" do - y = header + <<~INPUT -%% - -program: class ; - -class : keyword_class { code 1 } tSTRING { code 2 } keyword_end { code 3 } - | keyword_class tSTRING keyword_end { code 4 } - ; - -%% - - INPUT - grammar = Lrama::Parser.new(y).parse - - expect(grammar.nterms.sort_by(&:number)).to eq([ - Sym.new(id: T.new(type: T::Ident, s_value: "$accept"), alias_name: nil, number: 11, tag: nil, term: false, token_id: 0, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "program"), alias_name: nil, number: 12, tag: nil, term: false, token_id: 1, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "class"), alias_name: nil, number: 13, tag: T.new(type: T::Tag, s_value: ""), term: false, token_id: 2, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "$@1"), alias_name: nil, number: 14, tag: nil, term: false, token_id: 3, nullable: true), - Sym.new(id: T.new(type: T::Ident, s_value: "$@2"), alias_name: nil, number: 15, tag: nil, term: false, token_id: 4, nullable: true), - ]) - expect(grammar.rules).to eq([ - Rule.new( - id: 0, - lhs: grammar.find_symbol_by_s_value!("$accept"), - rhs: [ - grammar.find_symbol_by_s_value!("program"), - grammar.find_symbol_by_s_value!("EOI"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("EOI"), - lineno: 29, - ), - Rule.new( - id: 1, - lhs: grammar.find_symbol_by_s_value!("program"), - rhs: [ - grammar.find_symbol_by_s_value!("class"), - ], - code: nil, - nullable: false, - precedence_sym: nil, - lineno: 29, - ), - Rule.new( - id: 2, - lhs: grammar.find_symbol_by_s_value!("$@1"), - rhs: [], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " code 1 ")), - nullable: true, - precedence_sym: nil, - lineno: 31, - ), - Rule.new( - id: 3, - lhs: grammar.find_symbol_by_s_value!("$@2"), - rhs: [], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " code 2 ")), - nullable: true, - precedence_sym: nil, - lineno: 31, - ), - Rule.new( - id: 4, - lhs: grammar.find_symbol_by_s_value!("class"), - rhs: [ - grammar.find_symbol_by_s_value!("keyword_class"), - grammar.find_symbol_by_s_value!("$@1"), - grammar.find_symbol_by_s_value!("tSTRING"), - grammar.find_symbol_by_s_value!("$@2"), - grammar.find_symbol_by_s_value!("keyword_end"), - ], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " code 3 ")), - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("keyword_end"), - lineno: 31, - ), - Rule.new( - id: 5, - lhs: grammar.find_symbol_by_s_value!("class"), - rhs: [ - grammar.find_symbol_by_s_value!("keyword_class"), - grammar.find_symbol_by_s_value!("tSTRING"), - grammar.find_symbol_by_s_value!("keyword_end"), - ], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " code 4 ")), - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("keyword_end"), - lineno: 32, - ), - ]) - end - - describe "invalid_prec" do - it do - y = header + <<~INPUT -%% - -program: class ; - -class : keyword_class tSTRING %prec tPLUS keyword_end { code 1 } - ; - -%% - - INPUT - parser = Lrama::Parser.new(y) - - expect { parser.parse }.to raise_error("Ident after %prec") - end - - it do - y = header + <<~INPUT -%% - -program: class ; - -class : keyword_class { code 2 } tSTRING %prec "=" '!' keyword_end { code 3 } - ; - -%% - - INPUT - parser = Lrama::Parser.new(y) - - expect { parser.parse }.to raise_error("Char after %prec") - end - - it do - y = header + <<~INPUT -%% - -program: class ; - -class : keyword_class { code 4 } tSTRING '?' keyword_end %prec tEQ { code 5 } { code 6 } - ; - -%% - - INPUT - parser = Lrama::Parser.new(y) - - expect { parser.parse }.to raise_error("Multiple User_code after %prec") - end - end - - describe "\" in user code" do - it do - y = header + <<~INPUT -%% - -program: class ; - -class : keyword_class - { - func("}"); - } - ; - -%% - INPUT - grammar = Lrama::Parser.new(y).parse - codes = grammar.rules.map(&:code).compact - - expect(codes.count).to eq(1) - expect(codes[0].s_value).to eq(<<-STR.chomp) - - func("}"); - - STR - end - end - - describe "' in user code" do - it do - y = header + <<~INPUT -%% - -program: class ; - -class : keyword_class - { - func('}'); - } - ; - -%% - INPUT - grammar = Lrama::Parser.new(y).parse - codes = grammar.rules.map(&:code).compact - - expect(codes.count).to eq(1) - expect(codes[0].s_value).to eq(<<-STR.chomp) - - func('}'); - - STR - end - end - - describe "symbol number" do - it "is not duplicated" do - y = <<~INPUT -%{ -// Prologue -%} - -%union { - int i; - long l; - char *str; -} - -%token EOI 0 "EOI" -%token keyword_class -%token tNUMBER 6 -%token tSTRING -%token keyword_end "end" -%token tPLUS "+" -%token tMINUS "-" -%token tEQ "=" -%token tEQEQ "==" - -%% - -program: class ; - -class : keyword_class tSTRING keyword_end { code 1 } - ; - -%% - - INPUT - grammar = Lrama::Parser.new(y).parse - - expect(grammar.terms.sort_by(&:number)).to eq([ - Sym.new(id: T.new(type: T::Ident, s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "YYerror"), alias_name: "error", number: 1, tag: nil, term: true, token_id: 256, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "YYUNDEF"), alias_name: "\"invalid token\"", number: 2, tag: nil, term: true, token_id: 257, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "keyword_class"), alias_name: nil, number: 3, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 258, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "tNUMBER"), alias_name: nil, number: 4, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 6, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "tSTRING"), alias_name: nil, number: 5, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 259, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "keyword_end"), alias_name: "\"end\"", number: 6, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 260, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "tPLUS"), alias_name: "\"+\"", number: 7, tag: nil, term: true, token_id: 261, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "tMINUS"), alias_name: "\"-\"", number: 8, tag: nil, term: true, token_id: 262, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "tEQ"), alias_name: "\"=\"", number: 9, tag: nil, term: true, token_id: 263, nullable: false), - Sym.new(id: T.new(type: T::Ident, s_value: "tEQEQ"), alias_name: "\"==\"", number: 10, tag: nil, term: true, token_id: 264, nullable: false), - ]) - end - - it "tokens after precedence declarations have greater number than tokens defined by precedence declarations" do - y = <<~INPUT -%{ -// Prologue -%} - -%union { - int i; - long l; - char *str; -} - -%token EOI 0 "EOI" -%token keyword_class -%token tSTRING -%token keyword_end "end" -%token tEQ "=" - -%left '&' - -%token tEQEQ "==" - -%% - -program: class ; - -class : keyword_class tSTRING keyword_end { code 1 } - ; - -%% - - INPUT - grammar = Lrama::Parser.new(y).parse - - expect(grammar.terms.sort_by(&:number)).to eq([ - Sym.new(id: T.new(type: T::Ident, s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "YYerror"), alias_name: "error", number: 1, tag: nil, term: true, token_id: 256, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "YYUNDEF"), alias_name: "\"invalid token\"", number: 2, tag: nil, term: true, token_id: 257, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "keyword_class"), alias_name: nil, number: 3, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 258, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "tSTRING"), alias_name: nil, number: 4, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 259, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "keyword_end"), alias_name: "\"end\"", number: 5, tag: T.new(type: T::Tag, s_value: ""), term: true, token_id: 260, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Ident, s_value: "tEQ"), alias_name: "\"=\"", number: 6, tag: nil, term: true, token_id: 261, nullable: false, precedence: nil), - Sym.new(id: T.new(type: T::Char, s_value: "'&'"), alias_name: nil, number: 7, tag: nil, term: true, token_id: 38, nullable: false, precedence: Precedence.new(type: :left, precedence: 0)), - Sym.new(id: T.new(type: T::Ident, s_value: "tEQEQ"), alias_name: "\"==\"", number: 8, tag: nil, term: true, token_id: 262, nullable: false, precedence: nil), - ]) - end - end - - describe "user codes" do - describe "" do - it "is not duplicated" do - y = <<~INPUT -%{ -// Prologue -%} - -%union { - int i; -} - -%token EOI 0 "EOI" -%token tLAMBDA tARGS tBODY - -%% - -program: lambda ; - -lambda: tLAMBDA - { $1 = 1; $$ = 2; } - { $$ = 3; } - { $$ = 4; } - tARGS - { 5; } - tBODY - { $2; $3; $5; $7; $$ = 1; } - ; -%% - INPUT - grammar = Lrama::Parser.new(y).parse - - expect(grammar.rules).to eq([ - Rule.new( - id: 0, - lhs: grammar.find_symbol_by_s_value!("$accept"), - rhs: [ - grammar.find_symbol_by_s_value!("program"), - grammar.find_symbol_by_s_value!("EOI"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("EOI"), - lineno: 14, - ), - Rule.new( - id: 1, - lhs: grammar.find_symbol_by_s_value!("program"), - rhs: [ - grammar.find_symbol_by_s_value!("lambda"), - ], - code: nil, - nullable: false, - precedence_sym: nil, - lineno: 14, - ), - Rule.new( - id: 2, - lhs: grammar.find_symbol_by_s_value!("@1"), - rhs: [], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " $1 = 1; $$ = 2; ")), - nullable: true, - precedence_sym: nil, - lineno: 17, - ), - Rule.new( - id: 3, - lhs: grammar.find_symbol_by_s_value!("@2"), - rhs: [], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " $$ = 3; ")), - nullable: true, - precedence_sym: nil, - lineno: 18, - ), - Rule.new( - id: 4, - lhs: grammar.find_symbol_by_s_value!("$@3"), - rhs: [], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " $$ = 4; ")), - nullable: true, - precedence_sym: nil, - lineno: 19, - ), - Rule.new( - id: 5, - lhs: grammar.find_symbol_by_s_value!("$@4"), - rhs: [], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " 5; ")), - nullable: true, - precedence_sym: nil, - lineno: 21, - ), - Rule.new( - id: 6, - lhs: grammar.find_symbol_by_s_value!("lambda"), - rhs: [ - grammar.find_symbol_by_s_value!("tLAMBDA"), - grammar.find_symbol_by_s_value!("@1"), - grammar.find_symbol_by_s_value!("@2"), - grammar.find_symbol_by_s_value!("$@3"), - grammar.find_symbol_by_s_value!("tARGS"), - grammar.find_symbol_by_s_value!("$@4"), - grammar.find_symbol_by_s_value!("tBODY"), - ], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " $2; $3; $5; $7; $$ = 1; ")), - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("tBODY"), - lineno: 16, - ), - ]) - end - - it "can parse action with %empty" do - y = <<~INPUT -%{ -// Prologue -%} - -%union { - int i; -} - -%token EOI 0 "EOI" -%type emp - -%% - -program: emp ; - -emp: /* none */ - { $$; } - | %empty - { @$; } - | %empty - { @0; } - ; -%% - INPUT - grammar = Lrama::Parser.new(y).parse - - expect(grammar.rules).to eq([ - Rule.new( - id: 0, - lhs: grammar.find_symbol_by_s_value!("$accept"), - rhs: [ - grammar.find_symbol_by_s_value!("program"), - grammar.find_symbol_by_s_value!("EOI"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("EOI"), - lineno: 14, - ), - Rule.new( - id: 1, - lhs: grammar.find_symbol_by_s_value!("program"), - rhs: [ - grammar.find_symbol_by_s_value!("emp"), - ], - code: nil, - nullable: true, - precedence_sym: nil, - lineno: 14, - ), - Rule.new( - id: 2, - lhs: grammar.find_symbol_by_s_value!("emp"), - rhs: [ - ], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " $$; ")), - nullable: true, - precedence_sym: nil, - lineno: 17, - ), - Rule.new( - id: 3, - lhs: grammar.find_symbol_by_s_value!("emp"), - rhs: [ - ], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " @$; ")), - nullable: true, - precedence_sym: nil, - lineno: 19, - ), - Rule.new( - id: 4, - lhs: grammar.find_symbol_by_s_value!("emp"), - rhs: [ - ], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " @0; ")), - nullable: true, - precedence_sym: nil, - lineno: 21, - ), - ]) - end - - context "includes named references" do - it "can parse" do - y = <<~INPUT -%{ -// Prologue -%} - -%union { - int i; -} - -%token NUM -%type expr - -%% - -input : /* empty */ - | input line -; - -line : '\\n' - | expr '\\n' - { printf("\\t%.10g\\n", $expr); } -; - -expr[result]: NUM - | expr[left] expr[right] '+' - { $result = $left + $right; } - | expr expr '-' - { $$ = $1 - $2; } -; - INPUT - grammar = Lrama::Parser.new(y).parse - - expect(grammar.rules).to eq([ - Rule.new( - id: 0, - lhs: grammar.find_symbol_by_s_value!("$accept"), - rhs: [ - grammar.find_symbol_by_s_value!("input"), - grammar.find_symbol_by_s_value!("YYEOF"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("YYEOF"), - lineno: 14, - ), - Rule.new( - id: 1, - lhs: grammar.find_symbol_by_s_value!("input"), - rhs: [ - ], - code: nil, - nullable: true, - precedence_sym: nil, - lineno: 14, - ), - Rule.new( - id: 2, - lhs: grammar.find_symbol_by_s_value!("input"), - rhs: [ - grammar.find_symbol_by_s_value!("input"), - grammar.find_symbol_by_s_value!("line"), - ], - code: nil, - nullable: false, - precedence_sym: nil, - lineno: 15, - ), - Rule.new( - id: 3, - lhs: grammar.find_symbol_by_s_value!("line"), - rhs: [ - grammar.find_symbol_by_s_value!("'\\n'"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("'\\n'"), - lineno: 18, - ), - Rule.new( - id: 4, - lhs: grammar.find_symbol_by_s_value!("line"), - rhs: [ - grammar.find_symbol_by_s_value!("expr"), - grammar.find_symbol_by_s_value!("'\\n'"), - ], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " printf(\"\\t%.10g\\n\", $expr); ")), - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("'\\n'"), - lineno: 19, - ), - Rule.new( - id: 5, - lhs: grammar.find_symbol_by_s_value!("expr"), - rhs: [ - grammar.find_symbol_by_s_value!("NUM"), - ], - code: nil, - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("NUM"), - lineno: 23, - ), - Rule.new( - id: 6, - lhs: grammar.find_symbol_by_s_value!("expr"), - rhs: [ - grammar.find_symbol_by_s_value!("expr"), - grammar.find_symbol_by_s_value!("expr"), - grammar.find_symbol_by_s_value!("'+'"), - ], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " $result = $left + $right; ")), - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("'+'"), - lineno: 24, - ), - Rule.new( - id: 7, - lhs: grammar.find_symbol_by_s_value!("expr"), - rhs: [ - grammar.find_symbol_by_s_value!("expr"), - grammar.find_symbol_by_s_value!("expr"), - grammar.find_symbol_by_s_value!("'-'"), - ], - code: Code.new(type: :user_code, token_code: T.new(type: T::User_code, s_value: " $$ = $1 - $2; ")), - nullable: false, - precedence_sym: grammar.find_symbol_by_s_value!("'-'"), - lineno: 26, - ), - ]) - end - end - - context "includes invalid named references" do - it "raise an error" do - y = <<~INPUT -%{ -// Prologue -%} - -%union { - int i; -} - -%token NUM -%type expr - -%% - -input : /* empty */ - | input line -; - -line : '\\n' - | expr '\\n' - { printf("\\t%.10g\\n", $expr); } -; - -expr[result]: NUM - | expr[left] expr[right] '+' - { $results = $left + $right; } - | expr expr '-' - { $$ = $1 - $2; } -; - INPUT - - expect { Lrama::Parser.new(y).parse }.to raise_error("'results' is invalid name.") - end - end - end - end - end - - describe "#fill_symbol_number" do - it "fills token_id of Token::Char" do - y = <<~INPUT -%{ -// Prologue -%} - -%union { - int i; -} - -%token '\\b' "BS" -%token '\\f' "FF" -%token '\\n' "LF" -%token '\\r' "CR" -%token '\\t' "HT" -%token '\\v' "VT" - -%token keyword_class -%token tSTRING -%token keyword_end - -%% - -program: class ; - -class : keyword_class tSTRING keyword_end ; - -%% - INPUT - grammar = Lrama::Parser.new(y).parse - terms = grammar.terms.sort_by(&:number).map do |term| - [term.id.s_value, term.token_id] - end - - expect(terms).to eq([ - ["YYEOF", 0], - ["YYerror", 256], - ["YYUNDEF", 257], - ["'\\b'", 8], - ["'\\f'", 12], - ["'\\n'", 10], - ["'\\r'", 13], - ["'\\t'", 9], - ["'\\v'", 11], - ["keyword_class", 258], - ["tSTRING", 259], - ["keyword_end", 260], - ]) - end - end - - describe "#normalize_rules" do - describe "referring_symbol" do - it "uses a tag specified in code" do - y = <<~INPUT -%{ -// Prologue -%} - -%union { - int i; - long l; -} - -%token keyword_class -%token tSTRING -%token keyword_end - -%% - -program: class ; - -class : keyword_class tSTRING keyword_end - { $$; } - ; - -%% - INPUT - grammar = Lrama::Parser.new(y).parse - codes = grammar.rules.map(&:code) - - expect(codes.count).to eq(3) - expect(codes[0]).to be nil - expect(codes[1]).to be nil - expect(codes[2].references.count).to eq(1) - expect(codes[2].references[0].tag.s_value).to eq("") - end - end - end - - describe "Grammar#validate!" do - describe "#validate_no_declared_type_reference!" do - it "raises error when referred nterm, term and action have no tag so that type is not declared" do - y = <<~INPUT -%{ -// Prologue -%} - -%union { - int val; -} - -%token NUM - -%% - -program : stmt - ; - -stmt : {} {} expr { $$ = $1 + $2; } - ; - -expr : expr1 - | expr2 - ; - -expr1 : NUM { $$ = $1; } - ; - -expr2 : expr '+' expr { $$ = $1 + $3; } - ; - -%% - INPUT - - expect { Lrama::Parser.new(y).parse }.to raise_error(RuntimeError) do |e| - expect(e.message).to eq(<<~MSG.chomp) - $$ of 'stmt' has no declared type - $1 of 'stmt' has no declared type - $$ of 'expr1' has no declared type - $1 of 'expr1' has no declared type - $$ of 'expr2' has no declared type - $1 of 'expr2' has no declared type - $3 of 'expr2' has no declared type - MSG - end - end - end - end -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index fe7e706f..b00d8b69 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,7 +6,7 @@ # Created Groups based on the folder structures add_group "Grammar", "lib/lrama/grammar" add_group "Lexer", "lib/lrama/lexer" - add_group "Parser", "lib/lrama/parser" + # add_group "Parser", "lib/lrama/parser" add_group "Report", "lib/lrama/report" add_group "State", "lib/lrama/state/" add_group "States", "lib/lrama/states/" From ee8b2425bcffb43ca097c3f12c03038a90ebc008 Mon Sep 17 00:00:00 2001 From: Junichi Kobayashi Date: Thu, 19 Oct 2023 21:49:22 +0900 Subject: [PATCH 2/2] Rename NewParser to Parser --- .github/workflows/codespell.yaml | 2 +- .github/workflows/test.yaml | 2 +- Rakefile | 4 +- lib/lrama.rb | 3 +- lib/lrama/command.rb | 2 +- lib/lrama/{new_parser.rb => parser.rb} | 4 +- parser.y | 2 +- spec/lrama/context_spec.rb | 6 +-- spec/lrama/counterexamples_spec.rb | 8 ++-- .../{new_parser_spec.rb => parser_spec.rb} | 40 +++++++++---------- spec/lrama/states_spec.rb | 28 ++++++------- spec/spec_helper.rb | 2 +- 12 files changed, 51 insertions(+), 52 deletions(-) rename lib/lrama/{new_parser.rb => parser.rb} (99%) rename spec/lrama/{new_parser_spec.rb => parser_spec.rb} (98%) diff --git a/.github/workflows/codespell.yaml b/.github/workflows/codespell.yaml index 7632ba8e..df58a780 100644 --- a/.github/workflows/codespell.yaml +++ b/.github/workflows/codespell.yaml @@ -13,4 +13,4 @@ jobs: check_filenames: true check_hidden: true ignore_words_file: .codespellignore - exclude_file: lib/lrama/new_parser.rb + exclude_file: lib/lrama/parser.rb diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 06ff001a..1c2fe482 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -58,7 +58,7 @@ jobs: - name: Check for parser.rb is up to date run: | bundle exec rake build:racc_parser - git diff --color --no-ext-diff --ignore-submodules --exit-code lib/lrama/new_parser.rb + git diff --color --no-ext-diff --ignore-submodules --exit-code lib/lrama/parser.rb steep-check: runs-on: ubuntu-20.04 strategy: diff --git a/Rakefile b/Rakefile index 6a8ac011..077bf110 100644 --- a/Rakefile +++ b/Rakefile @@ -3,11 +3,11 @@ require "bundler/gem_tasks" namespace "build" do desc "build parser from parser.y by using Racc" task :racc_parser do - `bundle exec racc parser.y --embedded -o lib/lrama/new_parser.rb` + `bundle exec racc parser.y --embedded -o lib/lrama/parser.rb` end desc "build parser for debugging" task :racc_verbose_parser do - `bundle exec racc parser.y --embedded -o lib/lrama/new_parser.rb -t --log-file=parser.output` + `bundle exec racc parser.y --embedded -o lib/lrama/parser.rb -t --log-file=parser.output` end end diff --git a/lib/lrama.rb b/lib/lrama.rb index aa813a52..f9c5ec16 100644 --- a/lib/lrama.rb +++ b/lib/lrama.rb @@ -8,7 +8,7 @@ require "lrama/option_parser" require "lrama/options" require "lrama/output" -# require "lrama/parser" +require "lrama/parser" require "lrama/report" require "lrama/state" require "lrama/states" @@ -16,5 +16,4 @@ require "lrama/type" require "lrama/version" require "lrama/warning" -require "lrama/new_parser" require "lrama/new_lexer" diff --git a/lib/lrama/command.rb b/lib/lrama/command.rb index 213b7acb..5d8957da 100644 --- a/lib/lrama/command.rb +++ b/lib/lrama/command.rb @@ -8,7 +8,7 @@ def run(argv) warning = Lrama::Warning.new text = options.y.read options.y.close if options.y != STDIN - grammar = Lrama::NewParser.new(text).parse + grammar = Lrama::Parser.new(text).parse states = Lrama::States.new(grammar, warning, trace_state: (options.trace_opts[:automaton] || options.trace_opts[:closure])) states.compute context = Lrama::Context.new(states) diff --git a/lib/lrama/new_parser.rb b/lib/lrama/parser.rb similarity index 99% rename from lib/lrama/new_parser.rb rename to lib/lrama/parser.rb index dc0c77f7..efa87da8 100644 --- a/lib/lrama/new_parser.rb +++ b/lib/lrama/parser.rb @@ -666,7 +666,7 @@ def token_to_str(t) end ###### racc/parser.rb end module Lrama - class NewParser < Racc::Parser + class Parser < Racc::Parser module_eval(<<'...end parser.y/module_eval...', 'parser.y', 388) @@ -1787,5 +1787,5 @@ def _reduce_none(val, _values, result) val[0] end - end # class NewParser + end # class Parser end # module Lrama diff --git a/parser.y b/parser.y index 27b1566f..126da691 100644 --- a/parser.y +++ b/parser.y @@ -1,4 +1,4 @@ -class Lrama::NewParser +class Lrama::Parser rule input: prologue_declarations bison_declarations "%%" grammar epilogue_opt diff --git a/spec/lrama/context_spec.rb b/spec/lrama/context_spec.rb index d81d5964..a8ff640d 100644 --- a/spec/lrama/context_spec.rb +++ b/spec/lrama/context_spec.rb @@ -5,7 +5,7 @@ describe "basic" do it do y = File.read(fixture_path("context/basic.y")) - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute context = Lrama::Context.new(states) @@ -181,7 +181,7 @@ %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute context = Lrama::Context.new(states) @@ -230,7 +230,7 @@ %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute context = Lrama::Context.new(states) diff --git a/spec/lrama/counterexamples_spec.rb b/spec/lrama/counterexamples_spec.rb index 501d680d..f0cce980 100644 --- a/spec/lrama/counterexamples_spec.rb +++ b/spec/lrama/counterexamples_spec.rb @@ -50,7 +50,7 @@ end it "build counterexamples of S/R conflicts" do - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute counterexamples = Lrama::Counterexamples.new(states) @@ -249,7 +249,7 @@ end it "build counterexamples of R/R conflicts" do - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute counterexamples = Lrama::Counterexamples.new(states) @@ -326,7 +326,7 @@ end it "build counterexamples of S/R conflicts" do - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute counterexamples = Lrama::Counterexamples.new(states) @@ -407,7 +407,7 @@ end it "build counterexamples of S/R and R/R conflicts" do - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute counterexamples = Lrama::Counterexamples.new(states) diff --git a/spec/lrama/new_parser_spec.rb b/spec/lrama/parser_spec.rb similarity index 98% rename from spec/lrama/new_parser_spec.rb rename to spec/lrama/parser_spec.rb index 6833ac0d..6bae8ace 100644 --- a/spec/lrama/new_parser_spec.rb +++ b/spec/lrama/parser_spec.rb @@ -1,4 +1,4 @@ -RSpec.describe Lrama::NewParser do +RSpec.describe Lrama::Parser do T ||= Lrama::Lexer::Token Type = Lrama::Type Sym = Lrama::Grammar::Symbol @@ -41,7 +41,7 @@ describe '#parse' do it "basic" do y = File.read(fixture_path("common/basic.y")) - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse expect(grammar.union.code.s_value).to eq(<<-CODE.chomp) @@ -408,7 +408,7 @@ it "nullable" do y = File.read(fixture_path("common/nullable.y")) - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse expect(grammar.nterms.sort_by(&:number)).to eq([ Sym.new(id: T.new(type: T::Ident, s_value: "$accept"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 0, nullable: false), @@ -562,7 +562,7 @@ class : keyword_class tSTRING keyword_end { code 1 } %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse expect(grammar._rules).to eq([ [ @@ -605,7 +605,7 @@ class : keyword_class tSTRING keyword_end { code 1 } %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse expect(grammar.terms.sort_by(&:number)).to eq([ Sym.new(id: T.new(type: T::Ident, s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false, precedence: nil), @@ -661,7 +661,7 @@ class : keyword_class { code 1 } tSTRING { code 2 } keyword_end { code 3 } %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse expect(grammar.nterms.sort_by(&:number)).to eq([ Sym.new(id: T.new(type: T::Ident, s_value: "$accept"), alias_name: nil, number: 11, tag: nil, term: false, token_id: 0, nullable: false), @@ -756,7 +756,7 @@ class : keyword_class tSTRING %prec tPLUS keyword_end { code 1 } %% INPUT - parser = Lrama::NewParser.new(y) + parser = Lrama::Parser.new(y) expect { parser.parse }.to raise_error("Ident after %prec") end @@ -773,7 +773,7 @@ class : keyword_class { code 2 } tSTRING %prec "=" '!' keyword_end { code 3 } %% INPUT - parser = Lrama::NewParser.new(y) + parser = Lrama::Parser.new(y) expect { parser.parse }.to raise_error("Char after %prec") end @@ -790,7 +790,7 @@ class : keyword_class { code 4 } tSTRING '?' keyword_end %prec tEQ { code 5 } { %% INPUT - parser = Lrama::NewParser.new(y) + parser = Lrama::Parser.new(y) expect { parser.parse }.to raise_error("Multiple User_code after %prec") end @@ -811,7 +811,7 @@ class : keyword_class %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse codes = grammar.rules.map(&:code).compact expect(codes.count).to eq(1) @@ -838,7 +838,7 @@ class : keyword_class %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse codes = grammar.rules.map(&:code).compact expect(codes.count).to eq(1) @@ -883,7 +883,7 @@ class : keyword_class tSTRING keyword_end { code 1 } %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse expect(grammar.terms.sort_by(&:number)).to eq([ Sym.new(id: T.new(type: T::Ident, s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false), @@ -932,7 +932,7 @@ class : keyword_class tSTRING keyword_end { code 1 } %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse expect(grammar.terms.sort_by(&:number)).to eq([ Sym.new(id: T.new(type: T::Ident, s_value: "EOI"), alias_name: "\"EOI\"", number: 0, tag: nil, term: true, token_id: 0, nullable: false, precedence: nil), @@ -978,7 +978,7 @@ class : keyword_class tSTRING keyword_end { code 1 } ; %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse expect(grammar.rules).to eq([ Rule.new( @@ -1086,7 +1086,7 @@ class : keyword_class tSTRING keyword_end { code 1 } ; %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse expect(grammar.rules).to eq([ Rule.new( @@ -1177,7 +1177,7 @@ class : keyword_class tSTRING keyword_end { code 1 } { $$ = $1 - $2; } ; INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse expect(grammar.rules).to eq([ Rule.new( @@ -1311,7 +1311,7 @@ class : keyword_class tSTRING keyword_end { code 1 } ; INPUT - expect { Lrama::NewParser.new(y).parse }.to raise_error("'results' is invalid name.") + expect { Lrama::Parser.new(y).parse }.to raise_error("'results' is invalid name.") end end end @@ -1348,7 +1348,7 @@ class : keyword_class tSTRING keyword_end ; %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse terms = grammar.terms.sort_by(&:number).map do |term| [term.id.s_value, term.token_id] end @@ -1397,7 +1397,7 @@ class : keyword_class tSTRING keyword_end %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse codes = grammar.rules.map(&:code) expect(codes.count).to eq(3) @@ -1444,7 +1444,7 @@ class : keyword_class tSTRING keyword_end %% INPUT - expect { Lrama::NewParser.new(y).parse }.to raise_error(RuntimeError) do |e| + expect { Lrama::Parser.new(y).parse }.to raise_error(RuntimeError) do |e| expect(e.message).to eq(<<~MSG.chomp) $$ of 'stmt' has no declared type $1 of 'stmt' has no declared type diff --git a/spec/lrama/states_spec.rb b/spec/lrama/states_spec.rb index 01e383e2..e46c3759 100644 --- a/spec/lrama/states_spec.rb +++ b/spec/lrama/states_spec.rb @@ -5,7 +5,7 @@ describe '#compute' do it "basic" do y = File.read(fixture_path("common/basic.y")) - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -298,7 +298,7 @@ class go to state 5 it '#State#accessing_symbol' do y = File.read(fixture_path("common/basic.y")) - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -338,7 +338,7 @@ class go to state 5 describe '#reads_relation' do it do y = File.read(fixture_path("states/reads_relation.y")) - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -605,7 +605,7 @@ class go to state 5 describe '#includes_relation' do it do y = File.read(fixture_path("states/includes_relation.y")) - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -904,7 +904,7 @@ class go to state 5 %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -973,7 +973,7 @@ class go to state 5 %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -1063,7 +1063,7 @@ class go to state 5 %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -1180,7 +1180,7 @@ class go to state 5 %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -1277,7 +1277,7 @@ class go to state 5 %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -1426,7 +1426,7 @@ class go to state 5 %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -1598,7 +1598,7 @@ class go to state 5 %% INPUT - grammar = Lrama::NewParser.new(y).parse + grammar = Lrama::Parser.new(y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -1816,7 +1816,7 @@ class : keyword_class tSTRING keyword_end %prec tPLUS end it "has errors for r/r conflicts" do - grammar = Lrama::NewParser.new(header + y).parse + grammar = Lrama::Parser.new(header + y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -1840,7 +1840,7 @@ class : keyword_class tSTRING keyword_end %prec tPLUS end it "has errors for s/r conflicts and r/r conflicts" do - grammar = Lrama::NewParser.new(header + y).parse + grammar = Lrama::Parser.new(header + y).parse states = Lrama::States.new(grammar, warning) states.compute @@ -1864,7 +1864,7 @@ class : keyword_class tSTRING keyword_end %prec tPLUS end it "has warns for s/r conflicts and r/r conflicts" do - grammar = Lrama::NewParser.new(header + y).parse + grammar = Lrama::Parser.new(header + y).parse states = Lrama::States.new(grammar, warning) states.compute diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b00d8b69..fe7e706f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,7 +6,7 @@ # Created Groups based on the folder structures add_group "Grammar", "lib/lrama/grammar" add_group "Lexer", "lib/lrama/lexer" - # add_group "Parser", "lib/lrama/parser" + add_group "Parser", "lib/lrama/parser" add_group "Report", "lib/lrama/report" add_group "State", "lib/lrama/state/" add_group "States", "lib/lrama/states/"