from tock import *

"""
Explanation: Context-free grammars
End of explanation
"""


g = Grammar.from_lines(["S -> a T b",
                        "S -> b",
                        "T -> T a",
                        "T -> &"])
g

g.nonterminals

"""
Explanation: Creating CFGs
You can create a CFG either by reading from a file (using Grammar.from_file) or a list of strings (using Grammar.from_lines). The first rule's left-hand side is assumed to be the start symbol.
End of explanation
"""


g.is_contextfree()

"""
Explanation: A Grammar can be any unrestricted (type-0) grammar, but currently the grammar-reading functions can only read CFGs.
End of explanation
"""


m = from_grammar(g)
to_graph(m)

run(m, "a a b", show_stack=4)

"""
Explanation: Like RegularExpression objects, there isn't a lot you can do with Grammar objects other than convert them to automata.
From CFGs to PDAs
To convert to a PDA using a top-down construction, use the from_grammar function:
End of explanation
"""


m = from_grammar(g, mode="bottomup")
to_graph(m)

run(m, "a a b")

"""
Explanation: This diagram is a little hard to read, but one thing to note is the cycle between loop and 3.1. This is caused by the left-recursive rule T -&gt; T a, which the automaton applies an unbounded number of times.
Shift-reduce parsing
There's also a bottom-up version:
End of explanation
"""


g = Grammar.from_lines(["S -> a S c",
                        "S -> T",
                        "T -> b T",
                        "T -> &"])

m = from_grammar(g, mode='ll1')
m

m.is_deterministic()

run(m, "a a b c c", show_stack=5).only_path()

"""
Explanation: LL(1) parsing
End of explanation
"""


g = Grammar.from_lines([
    'S -> T -|',
    'T -> T l T r',
    'T -> &'
])

m = from_grammar(g, mode='lr0')
m

m.is_deterministic()

run(m, 'l l r l r r -|', show_stack=15).only_path()

"""
Explanation: LR parsing
Construction of an LR parser involves building the LR automaton:
End of explanation
"""


m = read_csv('examples/sipser-2-14.csv')
g = to_grammar(m).remove_useless()
g

"""
Explanation: You can visualize the LR automaton using grammars.lr_automaton, and you can also build an LR(1) parser using mode='lr1'.
From PDAs to CFGs
The conversion in the reverse direction, from PDA to CFG, is actually related to the algorithm that Tock uses internally to simulate PDAs. We use the remove_useless method to reduce the size of the converted CFG.
End of explanation
"""


