├── .gitignore
├── 01-Hello
├── 01-Hello.iml
├── Hello.g4
├── input.txt
└── test_hello.py
├── 03-Array
├── 03-Array.iml
├── ArrayInit.g4
├── README.md
├── input.txt
├── rewriter.py
└── test_array.py
├── 04-Calc
├── 04-Calc.iml
├── LabeledExpr.g4
├── MyVisitor.py
├── README.md
├── calc.py
└── t.expr
├── 04-Expr
├── 04-Expr.iml
├── Expr.g4
├── MyListener.py
├── README.md
├── t.expr
└── test_Expr.py
├── 04-ExtractInterface
├── 04-ExtractInterface.iml
├── Demo.java
├── ExtractInterfaceListener.py
├── Java.g4
├── README.md
└── test_extract.py
├── 04-Rows-visitor
├── 04-Rows-visitor.iml
├── README.md
├── Rows.g4
├── col.py
└── t.rows
├── 04-modechange
├── 04-modechange.iml
├── README.md
├── XMLLexer.g4
├── t.xml
└── test.py
├── 04-sempred
├── 04-sempred.iml
├── Data.g4
├── Readme.md
├── t.data
└── test_data.py
├── 07-LableRule
├── 07-LableRule.iml
├── LExpr.g4
├── README.md
├── t.expr
├── test_EvalContext.py
├── test_EvalListener.py
└── test_EvalVistor.py
├── 07-Property
├── 07-Property.iml
├── PropertyFile.g4
├── README.md
├── t.properties
├── test_as_loader.py
├── test_as_print.py
├── test_listener.py
└── test_visitor.py
├── 08-CSV
├── 08-CSV.iml
├── CSV.g4
├── CSV_Loader.py
├── README.md
└── t.csv
├── 08-CallGraph
├── 08-CallGraph.iml
├── CallGraph.py
├── CheckSymbols.py
├── Cymbol.g4
├── Readme.md
├── SymbolScope.py
├── output.dot
├── t.cymbol
├── vars.cymbol
└── vars2.cymbol
├── 08-JSON
├── 08-JSON.iml
├── JSON.g4
├── README.md
├── json2xml.py
└── t.json
├── 09-simple
├── README.md
├── Simple.g4
├── TestE_Listener.py
├── in1.txt
├── in2.txt
├── in3.txt
├── in4.txt
├── in5.txt
├── in6.txt
└── in7.txt
├── 10-CSV
├── 10-CSV.iml
├── CSV.g4
├── README.md
├── test_csv.py
└── users.csv
├── 10-Keyword
├── 10-Keyword.iml
├── Keywords.g4
├── input1.txt
├── input2.txt
├── input3.txt
└── test_Keyword.py
├── 10-calc
├── 10-calc.iml
├── Expr.g4
├── README.md
└── calc.py
├── 11-CppState
├── 11-CppState.iml
├── CppStat.g4
├── PredCppStat.g4
├── input.cpp
└── input2.cpp
├── 11-predicate_lexer
├── 11-predicate_lexer.iml
├── Enum2.g4
├── README.md
├── Temp.java
└── test_EnumLexer.py
├── 11-predicate_parser
├── 11-predicate_parser.iml
├── Enum.g4
├── README.md
└── Temp.java
├── 12-channel
├── 12-channel.iml
├── Cymbol.g4
├── README.md
├── shift_var_comments.py
└── t.cym
├── 12-id_as_keyword
├── IDKeyword.g4
├── PredKeyword.g4
├── input.txt
└── run.bat
├── 12-sea_of_text
├── Mode.txt
├── ModeTagsLexer.g4
├── ModeTagsParser.g4
└── Tags.g4
├── README.md
├── antlr.jar
├── antlr4module
├── bin
├── antlr-4.7.2-complete.jar
├── antlr4env.bat
└── pygrun
├── img
└── IDEA.png
└── requirements.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | __pycache__/
3 | *.tokens
4 | *.swp
5 |
6 | # Byte-compiled / optimized / DLL files
7 | __pycache__/
8 | *.py[cod]
9 | *$py.class
10 |
11 | # C extensions
12 | *.so
13 |
14 | # Distribution / packaging
15 | .Python
16 | build/
17 | develop-eggs/
18 | dist/
19 | downloads/
20 | eggs/
21 | .eggs/
22 | lib/
23 | lib64/
24 | parts/
25 | sdist/
26 | var/
27 | wheels/
28 | pip-wheel-metadata/
29 | share/python-wheels/
30 | *.egg-info/
31 | .installed.cfg
32 | *.egg
33 | MANIFEST
34 |
35 | # PyInstaller
36 | # Usually these files are written by a python script from a template
37 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
38 | *.manifest
39 | *.spec
40 |
41 | # Installer logs
42 | pip-log.txt
43 | pip-delete-this-directory.txt
44 |
45 | # Unit test / coverage reports
46 | htmlcov/
47 | .tox/
48 | .nox/
49 | .coverage
50 | .coverage.*
51 | .cache
52 | nosetests.xml
53 | coverage.xml
54 | *.cover
55 | *.py,cover
56 | .hypothesis/
57 | .pytest_cache/
58 | cover/
59 |
60 | # Translations
61 | *.mo
62 | *.pot
63 |
64 | # Django stuff:
65 | *.log
66 | local_settings.py
67 | db.sqlite3
68 | db.sqlite3-journal
69 |
70 | # Flask stuff:
71 | instance/
72 | .webassets-cache
73 |
74 | # Scrapy stuff:
75 | .scrapy
76 |
77 | # Sphinx documentation
78 | docs/_build/
79 |
80 | # PyBuilder
81 | .pybuilder/
82 | target/
83 |
84 | # Jupyter Notebook
85 | .ipynb_checkpoints
86 |
87 | # IPython
88 | profile_default/
89 | ipython_config.py
90 |
91 | # pyenv
92 | # For a library or package, you might want to ignore these files since the code is
93 | # intended to run in multiple environments; otherwise, check them in:
94 | # .python-version
95 |
96 | # pipenv
97 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
98 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
99 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
100 | # install all needed dependencies.
101 | #Pipfile.lock
102 |
103 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
104 | __pypackages__/
105 |
106 | # Celery stuff
107 | celerybeat-schedule
108 | celerybeat.pid
109 |
110 | # SageMath parsed files
111 | *.sage.py
112 |
113 | # Environments
114 | .env
115 | .venv
116 | env/
117 | venv/
118 | ENV/
119 | env.bak/
120 | venv.bak/
121 |
122 | # Spyder project settings
123 | .spyderproject
124 | .spyproject
125 |
126 | # Rope project settings
127 | .ropeproject
128 |
129 | # mkdocs documentation
130 | /site
131 |
132 | # mypy
133 | .mypy_cache/
134 | .dmypy.json
135 | dmypy.json
136 |
137 | # Pyre type checker
138 | .pyre/
139 |
140 | # pytype static type analyzer
141 | .pytype/
142 |
143 | # Cython debug symbols
144 | cython_debug/
145 |
146 | # static files generated from Django application using `collectstatic`
147 | media
148 | static
149 |
--------------------------------------------------------------------------------
/01-Hello/01-Hello.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/01-Hello/Hello.g4:
--------------------------------------------------------------------------------
1 | grammar Hello; // Define a grammar called Hello
2 | r : 'hello' ID ; // match keyword hello followed by an identifier
3 | ID : [a-z]+ ; // match lower-case identifiers
4 | WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines, \r (Windows)
5 |
--------------------------------------------------------------------------------
/01-Hello/input.txt:
--------------------------------------------------------------------------------
1 | hello world
--------------------------------------------------------------------------------
/01-Hello/test_hello.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from antlr4 import *
3 | from HelloLexer import HelloLexer
4 | from HelloParser import HelloParser
5 |
6 |
7 | def main(argv):
8 | input = FileStream(argv[1])
9 | lexer = HelloLexer(input)
10 | stream = CommonTokenStream(lexer)
11 | parser = HelloParser(stream)
12 | tree = parser.r()
13 | print(tree.toStringTree(recog=parser))
14 |
15 | if __name__ == '__main__':
16 | main(sys.argv)
17 |
--------------------------------------------------------------------------------
/03-Array/03-Array.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/03-Array/ArrayInit.g4:
--------------------------------------------------------------------------------
1 | /** Grammars always start with a grammar header. This grammar is called
2 | * ArrayInit and must match the filename: ArrayInit.g4
3 | */
4 | grammar ArrayInit;
5 |
6 | /** A rule called init that matches comma-separated values between {...}. */
7 | init : '{' value (',' value)* '}' ; // must match at least one value
8 |
9 | /** A value can be either a nested array/struct or a simple integer (INT) */
10 | value : init
11 | | INT
12 | ;
13 |
14 | // parser rules start with lowercase letters, lexer rules with uppercase
15 | INT : [0-9]+ ; // Define token INT as one or more digits
16 | WS : [ \t\r\n]+ -> skip ; // Define whitespace rule, toss it out
17 |
--------------------------------------------------------------------------------
/03-Array/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 | This example shows how to use listener to do simple translation of input array.
3 |
4 | # How to run
5 | ```
6 | % antlr4py3 ArrayInit.g4
7 | % pygrun ArrayInit init --tree input.txt
8 | [@0,0:0='{',<1>,1:0]
9 | [@1,1:2='99',<4>,1:1]
10 | [@2,3:3=',',<2>,1:3]
11 | [@3,5:5='3',<4>,1:5]
12 | [@4,6:6=',',<2>,1:6]
13 | [@5,8:10='451',<4>,1:8]
14 | [@6,11:11='}',<3>,1:11]
15 | [@7,12:11='',<-1>,1:12]
16 |
17 | % pygrun ArrayInit init --tokens input.txt
18 | (init {
19 | (value 99) ,
20 | (value 3) ,
21 | (value 451) })
22 |
23 | % python test_array.py input.txt
24 | (init { (value 99) , (value 3) , (value 451) })
25 | "\u0063\u0003\u01c3"
26 |
27 | ```
--------------------------------------------------------------------------------
/03-Array/input.txt:
--------------------------------------------------------------------------------
1 | {99, 3, 451}
--------------------------------------------------------------------------------
/03-Array/rewriter.py:
--------------------------------------------------------------------------------
1 | from ArrayInitListener import ArrayInitListener
2 |
3 |
4 | class RewriteListener(ArrayInitListener):
5 | # Enter a parse tree produced by ArrayInitParser#init.
6 | def enterInit(self, ctx):
7 | print("\"", end='')
8 |
9 | # Exit a parse tree produced by ArrayInitParser#init.
10 | def exitInit(self, ctx):
11 | print("\"", end='')
12 |
13 | # Enter a parse tree produced by ArrayInitParser#value.
14 | def enterValue(self, ctx):
15 | pass
16 |
17 | # Exit a parse tree produced by ArrayInitParser#value.
18 | def exitValue(self, ctx):
19 | data = ctx.INT().getText()
20 | print('\\u%04x' % int(data), end='')
--------------------------------------------------------------------------------
/03-Array/test_array.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from antlr4 import *
3 | from ArrayInitLexer import ArrayInitLexer
4 | from ArrayInitParser import ArrayInitParser
5 | from rewriter import RewriteListener
6 |
7 | def main(argv):
8 | istream = FileStream(argv[1])
9 | lexer = ArrayInitLexer(istream)
10 | stream = CommonTokenStream(lexer)
11 | parser = ArrayInitParser(stream)
12 | tree = parser.init()
13 | print(tree.toStringTree(recog=parser))
14 |
15 | walker = ParseTreeWalker()
16 | walker.walk(RewriteListener(), tree)
17 | print()
18 |
19 | if __name__ == '__main__':
20 | main(sys.argv)
21 |
--------------------------------------------------------------------------------
/04-Calc/04-Calc.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/04-Calc/LabeledExpr.g4:
--------------------------------------------------------------------------------
1 | grammar LabeledExpr; // rename to distinguish from Expr.g4
2 |
3 | prog: stat+ ;
4 |
5 | stat: expr NEWLINE # printExpr
6 | | ID '=' expr NEWLINE # assign
7 | | NEWLINE # blank
8 | ;
9 |
10 | expr: expr op=('*'|'/') expr # MulDiv
11 | | expr op=('+'|'-') expr # AddSub
12 | | INT # int
13 | | ID # id
14 | | '(' expr ')' # parens
15 | ;
16 |
17 | MUL : '*' ; // assigns token name to '*' used above in grammar
18 | DIV : '/' ;
19 | ADD : '+' ;
20 | SUB : '-' ;
21 | ID : [a-zA-Z]+ ; // match identifiers
22 | INT : [0-9]+ ; // match integers
23 | NEWLINE:'\r'? '\n' ; // return newlines to parser (is end-statement signal)
24 | WS : [ \t]+ -> skip ; // toss out whitespace
25 |
--------------------------------------------------------------------------------
/04-Calc/MyVisitor.py:
--------------------------------------------------------------------------------
1 | __author__ = 'jszheng'
2 |
3 | from LabeledExprVisitor import LabeledExprVisitor
4 | from LabeledExprParser import LabeledExprParser
5 |
6 |
7 | class MyVisitor(LabeledExprVisitor):
8 | def __init__(self):
9 | self.memory = {}
10 |
11 | def visitAssign(self, ctx):
12 | name = ctx.ID().getText()
13 | value = self.visit(ctx.expr())
14 | self.memory[name] = value
15 | return value
16 |
17 | def visitPrintExpr(self, ctx):
18 | value = self.visit(ctx.expr())
19 | print(value)
20 | return 0
21 |
22 | def visitInt(self, ctx):
23 | return ctx.INT().getText()
24 |
25 | def visitId(self, ctx):
26 | name = ctx.ID().getText()
27 | if name in self.memory:
28 | return self.memory[name]
29 | return 0
30 |
31 | def visitMulDiv(self, ctx):
32 | left = int(self.visit(ctx.expr(0)))
33 | right = int(self.visit(ctx.expr(1)))
34 | if ctx.op.type == LabeledExprParser.MUL:
35 | return left * right
36 | return left / right
37 |
38 | def visitAddSub(self, ctx):
39 | left = int(self.visit(ctx.expr(0)))
40 | right = int(self.visit(ctx.expr(1)))
41 | if ctx.op.type == LabeledExprParser.ADD:
42 | return left + right
43 | return left - right
44 |
45 | def visitParens(self, ctx):
46 | return self.visit(ctx.expr())
47 |
--------------------------------------------------------------------------------
/04-Calc/README.md:
--------------------------------------------------------------------------------
1 | # Calculator
2 | This example shows
3 | - Visitor Pattern
4 | - Use of Alternative Label
5 |
6 | # How to run
7 | ```
8 | % antlr4py3 -visitor -no-listener LabeledExpr.g4
9 | % type t.expr
10 | 193
11 | a = 5
12 | b = 6
13 | a+b*2
14 | (1+2)*3
15 |
16 | % python calc.py t.expr
17 | 193
18 | 17
19 | 9
20 | ```
--------------------------------------------------------------------------------
/04-Calc/calc.py:
--------------------------------------------------------------------------------
1 | __author__ = 'jszheng'
2 |
3 | import sys
4 | from antlr4 import *
5 | from antlr4.InputStream import InputStream
6 | from LabeledExprLexer import LabeledExprLexer
7 | from LabeledExprParser import LabeledExprParser
8 | from MyVisitor import MyVisitor
9 |
10 | if __name__ == '__main__':
11 | if len(sys.argv) > 1:
12 | input_stream = FileStream(sys.argv[1])
13 | else:
14 | input_stream = InputStream(sys.stdin.readline())
15 |
16 | lexer = LabeledExprLexer(input_stream)
17 | token_stream = CommonTokenStream(lexer)
18 | parser = LabeledExprParser(token_stream)
19 | tree = parser.prog()
20 |
21 | #lisp_tree_str = tree.toStringTree(recog=parser)
22 | #print(lisp_tree_str)
23 |
24 | visitor = MyVisitor()
25 | visitor.visit(tree)
26 |
--------------------------------------------------------------------------------
/04-Calc/t.expr:
--------------------------------------------------------------------------------
1 | 193
2 | a = 5
3 | b = 6
4 | a+b*2
5 | (1+2)*3
6 |
--------------------------------------------------------------------------------
/04-Expr/04-Expr.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/04-Expr/Expr.g4:
--------------------------------------------------------------------------------
1 | grammar Expr;
2 |
3 | /** The start rule; begin parsing here. */
4 | prog: stat+ ;
5 |
6 | stat: expr NEWLINE
7 | | ID '=' expr NEWLINE
8 | | NEWLINE
9 | ;
10 |
11 | expr: expr ('*'|'/') expr
12 | | expr ('+'|'-') expr
13 | | INT
14 | | ID
15 | | '(' expr ')'
16 | ;
17 |
18 | ID : [a-zA-Z]+ ; // match identifiers
19 | INT : [0-9]+ ; // match integers
20 | NEWLINE:'\r'? '\n' ; // return newlines to parser (is end-statement signal)
21 | WS : [ \t]+ -> skip ; // toss out whitespace
22 |
--------------------------------------------------------------------------------
/04-Expr/MyListener.py:
--------------------------------------------------------------------------------
1 | __author__ = 'jszheng'
2 |
3 | from ExprListener import ExprListener
4 |
5 |
6 | class MyListener(ExprListener):
7 | # Enter a parse tree produced by ExprParser#prog.
8 | def enterProg(self, ctx):
9 | print('EnterProg')
10 |
11 | # Exit a parse tree produced by ExprParser#prog.
12 | def exitProg(self, ctx):
13 | print('ExitProg')
14 |
15 |
16 | # Enter a parse tree produced by ExprParser#stat.
17 | def enterStat(self, ctx):
18 | print('EnterStat')
19 |
20 | # Exit a parse tree produced by ExprParser#stat.
21 | def exitStat(self, ctx):
22 | print('ExitStat')
23 |
24 |
25 | # Enter a parse tree produced by ExprParser#expr.
26 | def enterExpr(self, ctx):
27 | print('EnterExpr')
28 |
29 | # Exit a parse tree produced by ExprParser#expr.
30 | def exitExpr(self, ctx):
31 | print('ExitExpr')
32 |
33 |
34 |
--------------------------------------------------------------------------------
/04-Expr/README.md:
--------------------------------------------------------------------------------
1 | # How to run
2 | ```
3 | % pygrun Expr prog --tree t.expr
4 | (prog
5 | (stat
6 | (expr 193) \n)
7 | (stat a =
8 | (expr 5) \n)
9 | (stat b =
10 | (expr 6) \n)
11 | (stat
12 | (expr
13 | (expr a) +
14 | (expr
15 | (expr b) *
16 | (expr 2))) \n)
17 | (stat
18 | (expr
19 | (expr (
20 | (expr
21 | (expr 1) +
22 | (expr 2)) )) *
23 | (expr 3)) \n))
24 |
25 | % python test_Expr.py t.expr
26 | (prog
27 | (stat (expr 193) \n)
28 | (stat a = (expr 5) \n)
29 | (stat b = (expr 6) \n)
30 | (stat (expr (expr a) + (expr (expr b) * (expr 2))) \n)
31 | (stat (expr (expr ( (expr (expr 1) + (expr 2)) )) * (expr 3)) \n)
32 | )
33 | ```
--------------------------------------------------------------------------------
/04-Expr/t.expr:
--------------------------------------------------------------------------------
1 | 193
2 | a = 5
3 | b = 6
4 | a+b*2
5 | (1+2)*3
6 |
--------------------------------------------------------------------------------
/04-Expr/test_Expr.py:
--------------------------------------------------------------------------------
1 | __author__ = 'jszheng'
2 |
3 | import sys
4 | from antlr4 import *
5 | from antlr4.InputStream import InputStream
6 | from ExprLexer import ExprLexer
7 | from ExprParser import ExprParser
8 |
9 | if __name__ == '__main__':
10 | if len(sys.argv) > 1:
11 | input_stream = FileStream(sys.argv[1])
12 | else:
13 | input_stream = InputStream(sys.stdin.readline())
14 |
15 | lexer = ExprLexer(input_stream)
16 | token_stream = CommonTokenStream(lexer)
17 | parser = ExprParser(token_stream)
18 | tree = parser.prog()
19 |
20 | lisp_tree_str = tree.toStringTree(recog=parser)
21 | print(lisp_tree_str)
22 |
23 |
--------------------------------------------------------------------------------
/04-ExtractInterface/04-ExtractInterface.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/04-ExtractInterface/Demo.java:
--------------------------------------------------------------------------------
1 | /***
2 | * Excerpted from "The Definitive ANTLR 4 Reference",
3 | * published by The Pragmatic Bookshelf.
4 | * Copyrights apply to this code. It may not be used to create training material,
5 | * courses, books, articles, and the like. Contact us if you are in doubt.
6 | * We make no guarantees that this code is fit for any purpose.
7 | * Visit http://www.pragmaticprogrammer.com/titles/tpantlr2 for more book information.
8 | ***/
9 | import java.util.List;
10 | import java.util.Map;
11 | public class Demo {
12 | int f(int x, String y) { }
13 | int[ ] g(/*no args*/) { return null; }
14 | List