in src/ct/parser/rules.go [32:108]
func LoadRules(s string) *Rules {
terminalRules := map[itemType]set.Set{}
unaryRules := map[Element]set.Set{}
binaryRules := map[Element]set.Set{}
nonTerminalSet := set.New()
ruleType := unknownRule
lines := strings.Split(s, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
switch {
case strings.HasPrefix(line, "#terminals"):
ruleType = terminalRule
case strings.HasPrefix(line, "#nonterminals"):
ruleType = nonTerminalRule
}
if ruleType == unknownRule || len(line) == 0 || line[0] == '#' {
continue
}
values := strings.Split(line, "->")
if len(values) != 2 {
continue
}
slice.TrimSpace(values)
A := values[0]
list := strings.Split(values[1], "|")
slice.TrimSpace(list)
nonTerminalSet.Add(A)
switch ruleType {
case terminalRule:
for _, s := range list {
a := ItemType(s)
if _, ok := terminalRules[a]; !ok {
terminalRules[a] = set.New()
}
terminalRules[a].Add(A)
}
case nonTerminalRule:
for _, a := range list {
symbols := strings.Fields(a)
slice.TrimSpace(symbols)
switch len(symbols) {
case 0:
glog.Fatalf("Cannot read production rule: %s\n", line)
case 1:
e := NewUnary(symbols[0])
if _, ok := unaryRules[e]; !ok {
unaryRules[e] = set.New()
}
unaryRules[e].Add(A)
nonTerminalSet.Add(e.leftNonTerminal)
default:
e := NewBinary(symbols[0], symbols[1])
if _, ok := binaryRules[e]; !ok {
binaryRules[e] = set.New()
}
binaryRules[e].Add(A)
nonTerminalSet.Add(e.leftNonTerminal)
nonTerminalSet.Add(e.rightNonTerminal)
}
}
}
}
return &Rules{
terminalRules: terminalRules,
unaryRules: unaryRules,
binaryRules: binaryRules,
nonTerminalSet: nonTerminalSet,
}
}