Skip to content

Commit ebe1c70

Browse files
author
Jonathon Ian Belotti
committed
Implementing grammars and adding example ContextFree Grammars
1 parent c6462bc commit ebe1c70

8 files changed

+156
-0
lines changed

grammars/contextFree.py

+14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
from unrestricted import UnrestrictedGrammar
2+
from contextSensitive import ContextSensitiveGrammar
3+
from grammar import isVariable
4+
5+
class ContextFreeGrammar(ContextSensitiveGrammar):
6+
7+
def validRule(self, r ):
8+
if not super(ContextFreeGrammar, self).validRule(r):
9+
if r.rhs: return False
10+
elif len(r.lhs) != 1 or not isVariable(r.lhs[0]):
11+
return False
12+
return True
13+
14+
115
"""
216
Algorithm 4.2.1
317
Construction of the Set of Nullable Variables

grammars/contextSensitive

Whitespace-only changes.

grammars/contextSensitive.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from unrestricted import UnrestrictedGrammar
2+
3+
4+
class ContextSensitiveGrammar(UnrestrictedGrammar):
5+
6+
def validRule(self, r ):
7+
if not super(ContextFreeGrammar, self).validRule(r):
8+
return False
9+
elif len(r.rhs) < len(r.lhs):
10+
return False
11+
return True
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from contextFree import ContextFreeGrammar
2+
from grammar import Rule
3+
4+
def buildCFGWithChainRules():
5+
g = ContextFreeGrammar()
6+
rules = []
7+
rules.extend( Rule(["A"],["a"]), Rule(["A"],["a","A"]), Rule(["A"],["B"]))
8+
rules.extend( Rule(["B"],["b","B"]), Rule(["B"],["b"]), Rule(["B"],["C"]))
9+
g.addRules(rules)
10+
return g
11+
12+
def buildCFGWtihNullableVars():
13+
g = ContextFreeGrammar()
14+
rules = []
15+
rules.extend( Rule(["S"],["A","C","A"]), Rule(["A"],["a","A","a"]))
16+
rules.extend( Rule(["A"],["B"]), Rule(["A"],["C"]), Rule(["B"],["b","B"]))
17+
rules.extend( Rule(["B"],["b"]), Rule(["C"],["c","C"]), Rule(["C"],[]))
18+
g.addRules(rules)
19+
return g
20+
21+
def buildCFGWithRecursiveStartSymbol():
22+
g = ContextFreeGrammar()
23+
rules = []
24+
rules.extend( Rule(["S"],["a","S"]), Rule(["S"],["A","B"]), Rule(["S"],["A","C"]))
25+
rules.extend( Rule(["A"],["a","A"]), Rule(["A"],[]), Rule(["B"],["b","B"]))
26+
rules.extend( Rule(["B"],["b","S"]), Rule(["C"],["c","C"]), Rule(["C"],[]))
27+
g.addRules(rules)
28+
return g
29+
30+
def buildCFGWithVarsThatDontDeriveTerminalStrings():
31+
g = ContextFreeGrammar()
32+
rules = []
33+
rules.extend( Rule(["S"],["A","C"]), Rule(["S"],["B","S"]), Rule(["S"],["B"]))
34+
rules.extend( Rule(["A"],["a","A"]), Rule(["A"],["a","F"]), Rule(["B"],["C","F"]))
35+
rules.extend( Rule(["B"],["b"]), Rule(["C"],["c","C"]), Rule(["C"],["D"]))
36+
rules.extend( Rule(["D"],["a","D"]), Rule(["D"],["B","D"]), Rule(["D"],["C"]))
37+
rules.extend( Rule(["E"],["a","A"]), Rule(["E"],["B","S","A"]), Rule(["F"],["b","B"]))
38+
rules.extend( Rule(["F"],["b"]))
39+
g.addRules(rules)
40+
return g
41+
42+
def buildCFGForReachableVars:
43+
g = ContextFreeGrammar()
44+
rules = []
45+
rules.extend( Rule(["S"],["B","S"]), Rule(["S"],["B"]), Rule(["A"],["a","A"]))
46+
rules.extend( Rule(["A"],["a","F"]), Rule(["B"],["b"]), Rule(["E"],["a","A"]))
47+
rules.extend( Rule(["E"],["B","S","A"]), Rule(["F"],["b","B"]), Rule(["F"],["b"]))
48+
g.addRules(rules)
49+
return g

grammars/grammar.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
STARTSYMBOL = "S"
3+
ALT_STARTSYMBOL = "S`"
4+
5+
def isVariable( elem ):
6+
return True if elem.isupper() else (True if elem == ALT_STARTSYMBOL else False)
7+
8+
def isTerminal( elem ):
9+
return True if elem.isLower() else False
10+
11+
class Rule(object):
12+
13+
def __init__(self, lhs, rhs=None):
14+
self.lhs = lhs.split(",")
15+
self.rhs = rhs.split(",")
16+
17+
def __str__(self):
18+
if(self.rhs):
19+
return " ".join(self.lhs) + " -> " + " ".join(self.rhs)
20+
else:
21+
return " ".join(self.lhs) + " -> null"

grammars/regular.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from contextFree import ContextFreeGrammar
2+
from grammar import isVariable, isTerminal
3+
4+
class RegularGrammar(ContextFreeGrammar):
5+
6+
def validRule(self, r ):
7+
if not super(RegularGrammar, self).validRule(r):
8+
return False
9+
elif not r.rhs: # rhs is null - valid
10+
return True
11+
elif len(r.rhs) == 2 and isTerminal(r.rhs[0]) and isVariable(r.rhs[1]):
12+
return True
13+
elif len(r.rhs) == 1 and isTerminal(r.lhs[0]):
14+
return True
15+
return False

grammars/rule.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

grammars/unrestricted.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from grammar import isVariable, isTerminal, STARTSYMBOL, ALT_STARTSYMBOL
2+
3+
class UnrestrictedGrammar(object):
4+
5+
def __init__(self):
6+
self.rules = []
7+
self.vars = set()
8+
self.terminals = set()
9+
10+
def __str__(self):
11+
output = ""
12+
output += "VARIABLES: " + ",".join(self.vars) + '\n'
13+
output += "TERMINALS: " + ",".join(self.terminals) + '\n'
14+
output += "RULES: " + '\n' + [(str(rule) + '\n') for rule in self.rules]
15+
return output
16+
17+
def addRules( rules ):
18+
if all(validRule(r) for r in rules):
19+
self.rules.extend(rules)
20+
return True
21+
else:
22+
return False
23+
24+
def addRule( self, r ):
25+
if validRule(r):
26+
self.rules.append(r)
27+
return True
28+
else: return False
29+
30+
def validRule( self, r ):
31+
if r.lhs: return True
32+
else: return False
33+
34+
def updateVarsAndTerminals(self, rule=None):
35+
if rule:
36+
self.vars.update([x for x in (rule.lhs + rule.rhs) if isVariable(x)])
37+
self.terminals.update([x for x in (rule.lhs + rule.rhs) if isTerminal(x)])
38+
else:
39+
self.vars = set()
40+
self.terminals = set()
41+
for r in self.rules:
42+
updateVarsAndTerminals(self, rule=r)
43+
44+
def getStartSymbol(self):
45+
return ALT_STARTSYMBOL if ALT_STARTSYMBOL in self.vars else STARTSYMBOL

0 commit comments

Comments
 (0)