lib/antelope/ace/grammar/productions.rb in antelope-0.1.8 vs lib/antelope/ace/grammar/productions.rb in antelope-0.1.9

- old
+ new

@@ -33,21 +33,24 @@ # @param value [String, Symbol, #intern] the token's symbol to # check. # @return [Token] def find_token(value) value = value.intern + if productions.key?(value) - Token::Nonterminal.new(value) + typed_nonterminals.find { |term| term.name == value } || + Token::Nonterminal.new(value) elsif terminal = terminals. find { |term| term.name == value } terminal elsif value == :error Token::Error.new elsif [:nothing, :ε].include?(value) Token::Epsilon.new else - raise UndefinedTokenError, "Could not find a token named #{value.inspect}" + raise UndefinedTokenError, "Could not find a token " \ + "named #{value.inspect}" end end private @@ -86,26 +89,48 @@ # # @param rule [Hash] the compiler's rule. # @param id [Numeric] the id for the production. # @return [Production] def generate_production_for(rule, id) - left = rule[:label] - items = rule[:set].map { |_| find_token(_) } + left = Token::Nonterminal.new(rule[:label]) + items = rule[:set].map { |_| find_token(_[0]) } prec = if rule[:prec].empty? items.select(&:terminal?).last else - find_token(rule[:prec]) + rule[:prec].intern end - unless rule[:prec].empty? - puts "PREC, #{prec.inspect}" + prec = precedence_for(prec) + left.type = type_for(rule[:label]) + left.id = rule[:label_id] + + rule[:set].each_with_index do |tok, i| + items[i] = items[i].dup + items[i].id = tok[1] end - prec = precedence_for(prec) + Production.new(left, items, rule[:block], prec, id + 1) + end - Production.new(Token::Nonterminal.new(left), items, - rule[:block], prec, id + 1) + # Returns the defined type for the given token name. + # Uses the `%type` directive to infer the corresponding types. + # + # @param token [Symbol] the token to check for + # types. + def type_for(token) + token = find_token(token) unless token.is_a?(Token) + + case token + when Token::Nonterminal + token.type + when Token::Terminal + token.type + when Token::Epsilon + "" + when Token::Error + "" + end end # Creates the default production for the grammar. The left # hand side of the production is the `:$start` symbol, with # the right hand side being the first rule's left-hand side @@ -114,10 +139,10 @@ # # @return [Production] def default_production Production.new(Token::Nonterminal.new(:$start), [ Token::Nonterminal.new(@compiler.rules.first[:label]), - Token::Terminal.new(:"$") + Token::Terminal.new(:$end) ], "", precedence.last, 0) end end end end