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