!cat Grammar.g4

"""
Explanation: Converting a Grammar into <span style="font-variant:small-caps;">Html</span>
You should store the  stored in the file Grammar.g4.  This grammar should describe the lexical structure of the grammar for the language 
C that is contained in the file 
<a href="https://github.com/karlstroetmann/Formal-Languages/blob/master/Exercises/Grammar2HTML-Antlr/c-grammar.g"><tt>c-grammar.g</tt></a>.
Your grammar <b style="color:red">must not</b> use the string rule as a variable name.  The reason is that rule is a variable that is already used in the parser generated by 
<span style="font-variant:small-caps;">Antlr</span>.
You grammar should generate an abstract syntax tree that conforms to the following type specification:
Grammar: List&lt;Rule&gt;
Rule:    Pair&lt;String, List&lt;Body&gt;&gt;
Body:    List&lt;Item&gt;
Item:    Pair&lt;'var', String&gt; + Pair&lt;'token', String&gt; + Pair&lt;'literal', String&gt;
End of explanation
"""


!cat c-grammar.g

"""
Explanation: The file c-grammar.g contains a context-free grammar for the language C.
End of explanation
"""


!antlr4 -Dlanguage=Python3 Grammar.g4

from GrammarLexer  import GrammarLexer
from GrammarParser import GrammarParser
import antlr4

"""
Explanation: Our goal is to convert this grammar into an <span style="font-variant:small-caps;">Html</span> <a href="c-grammar.html">file</a>.
We start by generating both scanner and parser.
End of explanation
"""


def grammar_2_string(grammar):
        result  = ''
        result += '<html>\n'
        result += '<head>\n'
        result += '<title>Grammar</title>\n'
        result += '</head>\n'
        result += '<body>\n'
        result += '<table>\n'
        for rule in grammar:
            result += rule_2_string(rule)
        result += '</table>\n'
        result += '</body>\n'
        result += '</html>\n'            
        return result

"""
Explanation: The function grammar_2_string takes a list of grammar rules as its input and renders these rules as an <span style="font-variant:small-caps;">Html</span> file.
End of explanation
"""


def rule_2_string(rule):
    head, body = rule
    result  = ''
    result += '<tr>\n'
    result += '<td style="text-align:right"><a name="' + head + '"><em>' + head + '<em></a></td>\n'
    result += '<td><code>:</code></td>\n'
    result += '<td>' +  body_2_string(body[0]) + '</td>'
    result += '</tr>\n'
    for i in range(1, len(body)):
        result += '<tr><td></td><td><code>|</code></td><td>'
        result += body_2_string(body[i])
        result += '</td></tr>\n'
    result += '<tr><td></td><td><code>;</code></td><tr>\n\n'
    return result

"""
Explanation: The function rule_2_string takes a grammar rule $r$ as its input and transforms this rule into an <span style="font-variant:small-caps;">Html</span> 
string.  Here the grammar rule $r$ has the form
$$ r = (V, L) $$
where $V$ is the name of the variable defined by $r$ and $L$ is a list of <em style="color:blue">grammar rule bodies</em>.  A single grammar rule
body is a list of <em style="color:blue">grammar items</em>.  A grammar item is either a non-terminal, a token or a literal.
End of explanation
"""


def body_2_string(body):
    result = ''
    if len(body) > 0:
        for item in body:
            result += item_2_string(item) + ' '
    else:
        result += '<code>/* empty */</code>'
    return result

"""
Explanation: The function body_2_string takes a list of grammar items as its inputs and turns them into an <span style="font-variant:small-caps;">Html</span> string.
End of explanation
"""


def item_2_string(item):
    kind, contend = item
    if kind == 'var':
        return '<a href="#' + contend + '"><em>' + contend + '</em></a>'
    else:
        return '<code>' + contend + '</code>'

def main():
    input_stream  = antlr4.FileStream('c-grammar.g')
    lexer         = GrammarLexer(input_stream)
    token_stream  = antlr4.CommonTokenStream(lexer)
    parser        = GrammarParser(token_stream)
    grammar       = parser.start()
    result        = grammar_2_string(grammar.g)
    file = open('c-grammar.html', 'w')
    file.write(result)

main()

!open c-grammar.html

"""
Explanation: The function item_2_string takes a grammar item as its inputs and turns the item into an <span style="font-variant:small-caps;">Html</span> string.
An item represents either a non-terminal or a terminal.  If it represents a non-terminal it has the form
$$(\texttt{'var'}, \textrm{name}) $$
where $\textrm{name}$ is the name of the variable. Otherwise it has the form
$$(\textrm{kind}, \textrm{name}), $$
where $\textrm{kind}$ is either token or literal.
End of explanation
"""


!rm *.py *.tokens *.interp

"""
Explanation: The command below cleans the directory.  If you are running windows, you have to replace rmwith del.
End of explanation
"""


