How To Build a Yacc?(10)
2005-12-28 01:06
399 查看
将Vocab和Rule功能组合起来作为一个RuleParser类来提供分析rule_file的功能是个不错的主意,因为对这两个类而言并没有太大的重用的意义,只不过是为了将错误的出现尽可能的控制在局部。
class TestCompiler < Test::Unit::TestCase
def test_rule_parser
create_rule_file
p = RuleParser.new("rulefile")
assert(p.rules[0].lt == "nil")
assert(p.rules[0].rt == ["function_decl"])
assert(p.vocabs.identify("function") == Vocab::TERMINAL)
end
end
有了Vocab和Rule,实现RuleParser只是举手之劳。
class RuleParser
def initialize(file_name)
@vocabs = Vocab.new
@rules = Array.new
compile(file_name)
end
@@directive = 0
DIRECTIVE = "%%"
####################################################
# 对于 yacc的输入规则文件进行解析
# 将文件中定义的token和rule分别存入@vocabs, @rules
# 定义文件分两段:
# %%
# {第一段:token definition}
# %%
# {第二段:rule definition}
# %%
####################################################
def compile(file_name)
file = File.open(file_name, "r")
no = 0
begin
file.each do |line|
no = no+1
if line.strip().chomp() == DIRECTIVE
@@directive = @@directive + 1
next
end
# @@directive == 0 not started, continue
# @@directive == 1 start parse terminals
# @@directive == 2 start parse rules
# @@directive == 3 end parse
case @@directive
when 0
next
when 1
if !add_terminal(line)
error(no, line, "parse terminal error")
end
when 2
rule = parse_rule(line)
if !rule
error(no, line, "parse nonterminal error")
end
add_nonterminal(rule)
when 3
break
end # end when
end # end for each
rescue
raise
ensure
file.close()
end # end begin...
end
def add_terminal(line)
@vocabs.add_terminal(line)
end
def add_nonterminal(rule)
@vocabs.add_nonterminals(rule.vocabs())
end
def parse_rule(line)
rule = Rule.parse(line)
@rules.push(rule)
return rule
end
def error(no, line, msg)
raise "Error #{msg} in Line #{no}, #{line}."
end
private :error
attr_reader :rules, :vocabs
end
实际上,对RuleParser的test case的设计,无意中凸显了一个事实,那就是应该将RuleParser设计为一个interface, 对外提供至少两个方法:get_rules(分析rule_file得到的rule集合);get_vocabs(分析rule_file得到的vocab集合)。这样,Yacc类就不必依赖于RuleParser的实现,意味着Yacc不必知晓rule_file的特定格式,这些细节只应该由RuleParser的实现类来关心。
在ruby这种动态语言里。。只要你设计出一个类提供rules,vocabs两个属性就好。。
class TestCompiler < Test::Unit::TestCase
def test_rule_parser
create_rule_file
p = RuleParser.new("rulefile")
assert(p.rules[0].lt == "nil")
assert(p.rules[0].rt == ["function_decl"])
assert(p.vocabs.identify("function") == Vocab::TERMINAL)
end
end
有了Vocab和Rule,实现RuleParser只是举手之劳。
class RuleParser
def initialize(file_name)
@vocabs = Vocab.new
@rules = Array.new
compile(file_name)
end
@@directive = 0
DIRECTIVE = "%%"
####################################################
# 对于 yacc的输入规则文件进行解析
# 将文件中定义的token和rule分别存入@vocabs, @rules
# 定义文件分两段:
# %%
# {第一段:token definition}
# %%
# {第二段:rule definition}
# %%
####################################################
def compile(file_name)
file = File.open(file_name, "r")
no = 0
begin
file.each do |line|
no = no+1
if line.strip().chomp() == DIRECTIVE
@@directive = @@directive + 1
next
end
# @@directive == 0 not started, continue
# @@directive == 1 start parse terminals
# @@directive == 2 start parse rules
# @@directive == 3 end parse
case @@directive
when 0
next
when 1
if !add_terminal(line)
error(no, line, "parse terminal error")
end
when 2
rule = parse_rule(line)
if !rule
error(no, line, "parse nonterminal error")
end
add_nonterminal(rule)
when 3
break
end # end when
end # end for each
rescue
raise
ensure
file.close()
end # end begin...
end
def add_terminal(line)
@vocabs.add_terminal(line)
end
def add_nonterminal(rule)
@vocabs.add_nonterminals(rule.vocabs())
end
def parse_rule(line)
rule = Rule.parse(line)
@rules.push(rule)
return rule
end
def error(no, line, msg)
raise "Error #{msg} in Line #{no}, #{line}."
end
private :error
attr_reader :rules, :vocabs
end
实际上,对RuleParser的test case的设计,无意中凸显了一个事实,那就是应该将RuleParser设计为一个interface, 对外提供至少两个方法:get_rules(分析rule_file得到的rule集合);get_vocabs(分析rule_file得到的vocab集合)。这样,Yacc类就不必依赖于RuleParser的实现,意味着Yacc不必知晓rule_file的特定格式,这些细节只应该由RuleParser的实现类来关心。
在ruby这种动态语言里。。只要你设计出一个类提供rules,vocabs两个属性就好。。
相关文章推荐
- How To Build a Yacc?(3)
- How To Build a Yacc?(8)
- How To Build a Yacc?(12)
- How To Build a Yacc?(4)
- How To Build a Yacc?(13)
- How To Build a Yacc?(5)
- How To Build a Yacc?(14)
- How To Build a Yacc?(6)
- How To Build a Yacc Series
- How To Build a Yacc?(7)
- How To Build a Yacc
- How To Build a Yacc?(9)
- How To Build a Yacc?(1)
- How To Build a Yacc?(2)
- How To Build a Yacc?(11)
- How to Build Office Developer Tools Projects with TFS Team Build 2012
- How to Build a Chat Bot Using Azure Bot Service and Train It with LUIS
- HOWTO build arm-linux toolchain for ARM/XSCALE
- How to Build a RESTful API Web Service with PHP
- 5+ Best Examples of How to Build a DIY Self-Balancing Robot