diff --git a/requirements.txt b/requirements.txt index 796b440..3adac30 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -antlr=4.13.1=ha770c72_0 -antlr4-tools=0.2.1=pypi_0 -ply=3.11=py311h06a4308_0 +antlr4-tools>=0.2.1 +ply>=3.11 +antlr4-python3-runtime>=4.9 diff --git a/src/ArithLexer.interp b/src/ArithLexer.interp new file mode 100644 index 0000000..9f6a130 --- /dev/null +++ b/src/ArithLexer.interp @@ -0,0 +1,38 @@ +token literal names: +null +'+' +'*' +'**' +'(' +')' +null +null + +token symbolic names: +null +null +null +null +null +null +NUMBER +WS + +rule names: +T__0 +T__1 +T__2 +T__3 +T__4 +NUMBER +WS + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 7, 40, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 5, 5, 30, 8, 5, 10, 5, 12, 5, 33, 9, 5, 3, 5, 35, 8, 5, 1, 6, 1, 6, 1, 6, 1, 6, 0, 0, 7, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 1, 0, 3, 1, 0, 49, 57, 1, 0, 48, 57, 3, 0, 9, 10, 13, 13, 32, 32, 41, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 1, 15, 1, 0, 0, 0, 3, 17, 1, 0, 0, 0, 5, 19, 1, 0, 0, 0, 7, 22, 1, 0, 0, 0, 9, 24, 1, 0, 0, 0, 11, 34, 1, 0, 0, 0, 13, 36, 1, 0, 0, 0, 15, 16, 5, 43, 0, 0, 16, 2, 1, 0, 0, 0, 17, 18, 5, 42, 0, 0, 18, 4, 1, 0, 0, 0, 19, 20, 5, 42, 0, 0, 20, 21, 5, 42, 0, 0, 21, 6, 1, 0, 0, 0, 22, 23, 5, 40, 0, 0, 23, 8, 1, 0, 0, 0, 24, 25, 5, 41, 0, 0, 25, 10, 1, 0, 0, 0, 26, 35, 5, 48, 0, 0, 27, 31, 7, 0, 0, 0, 28, 30, 7, 1, 0, 0, 29, 28, 1, 0, 0, 0, 30, 33, 1, 0, 0, 0, 31, 29, 1, 0, 0, 0, 31, 32, 1, 0, 0, 0, 32, 35, 1, 0, 0, 0, 33, 31, 1, 0, 0, 0, 34, 26, 1, 0, 0, 0, 34, 27, 1, 0, 0, 0, 35, 12, 1, 0, 0, 0, 36, 37, 7, 2, 0, 0, 37, 38, 1, 0, 0, 0, 38, 39, 6, 6, 0, 0, 39, 14, 1, 0, 0, 0, 3, 0, 31, 34, 1, 6, 0, 0] \ No newline at end of file diff --git a/src/ArithLexer.py b/src/ArithLexer.py new file mode 100644 index 0000000..55e067a --- /dev/null +++ b/src/ArithLexer.py @@ -0,0 +1,64 @@ +# Generated from arith.g4 by ANTLR 4.13.1 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + + +def serializedATN(): + return [ + 4,0,7,40,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2, + 6,7,6,1,0,1,0,1,1,1,1,1,2,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,5,5, + 5,30,8,5,10,5,12,5,33,9,5,3,5,35,8,5,1,6,1,6,1,6,1,6,0,0,7,1,1,3, + 2,5,3,7,4,9,5,11,6,13,7,1,0,3,1,0,49,57,1,0,48,57,3,0,9,10,13,13, + 32,32,41,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0, + 0,0,0,11,1,0,0,0,0,13,1,0,0,0,1,15,1,0,0,0,3,17,1,0,0,0,5,19,1,0, + 0,0,7,22,1,0,0,0,9,24,1,0,0,0,11,34,1,0,0,0,13,36,1,0,0,0,15,16, + 5,43,0,0,16,2,1,0,0,0,17,18,5,42,0,0,18,4,1,0,0,0,19,20,5,42,0,0, + 20,21,5,42,0,0,21,6,1,0,0,0,22,23,5,40,0,0,23,8,1,0,0,0,24,25,5, + 41,0,0,25,10,1,0,0,0,26,35,5,48,0,0,27,31,7,0,0,0,28,30,7,1,0,0, + 29,28,1,0,0,0,30,33,1,0,0,0,31,29,1,0,0,0,31,32,1,0,0,0,32,35,1, + 0,0,0,33,31,1,0,0,0,34,26,1,0,0,0,34,27,1,0,0,0,35,12,1,0,0,0,36, + 37,7,2,0,0,37,38,1,0,0,0,38,39,6,6,0,0,39,14,1,0,0,0,3,0,31,34,1, + 6,0,0 + ] + +class ArithLexer(Lexer): + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + T__0 = 1 + T__1 = 2 + T__2 = 3 + T__3 = 4 + T__4 = 5 + NUMBER = 6 + WS = 7 + + channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] + + modeNames = [ "DEFAULT_MODE" ] + + literalNames = [ "", + "'+'", "'*'", "'**'", "'('", "')'" ] + + symbolicNames = [ "", + "NUMBER", "WS" ] + + ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "NUMBER", "WS" ] + + grammarFileName = "arith.g4" + + def __init__(self, input=None, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.13.1") + self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) + self._actions = None + self._predicates = None + + diff --git a/src/ArithLexer.tokens b/src/ArithLexer.tokens new file mode 100644 index 0000000..d3047b4 --- /dev/null +++ b/src/ArithLexer.tokens @@ -0,0 +1,12 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +NUMBER=6 +WS=7 +'+'=1 +'*'=2 +'**'=3 +'('=4 +')'=5 diff --git a/src/PowerLexer.interp b/src/PowerLexer.interp new file mode 100644 index 0000000..9f6a130 --- /dev/null +++ b/src/PowerLexer.interp @@ -0,0 +1,38 @@ +token literal names: +null +'+' +'*' +'**' +'(' +')' +null +null + +token symbolic names: +null +null +null +null +null +null +NUMBER +WS + +rule names: +T__0 +T__1 +T__2 +T__3 +T__4 +NUMBER +WS + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 7, 40, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 5, 5, 30, 8, 5, 10, 5, 12, 5, 33, 9, 5, 3, 5, 35, 8, 5, 1, 6, 1, 6, 1, 6, 1, 6, 0, 0, 7, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 1, 0, 3, 1, 0, 49, 57, 1, 0, 48, 57, 3, 0, 9, 10, 13, 13, 32, 32, 41, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 1, 15, 1, 0, 0, 0, 3, 17, 1, 0, 0, 0, 5, 19, 1, 0, 0, 0, 7, 22, 1, 0, 0, 0, 9, 24, 1, 0, 0, 0, 11, 34, 1, 0, 0, 0, 13, 36, 1, 0, 0, 0, 15, 16, 5, 43, 0, 0, 16, 2, 1, 0, 0, 0, 17, 18, 5, 42, 0, 0, 18, 4, 1, 0, 0, 0, 19, 20, 5, 42, 0, 0, 20, 21, 5, 42, 0, 0, 21, 6, 1, 0, 0, 0, 22, 23, 5, 40, 0, 0, 23, 8, 1, 0, 0, 0, 24, 25, 5, 41, 0, 0, 25, 10, 1, 0, 0, 0, 26, 35, 5, 48, 0, 0, 27, 31, 7, 0, 0, 0, 28, 30, 7, 1, 0, 0, 29, 28, 1, 0, 0, 0, 30, 33, 1, 0, 0, 0, 31, 29, 1, 0, 0, 0, 31, 32, 1, 0, 0, 0, 32, 35, 1, 0, 0, 0, 33, 31, 1, 0, 0, 0, 34, 26, 1, 0, 0, 0, 34, 27, 1, 0, 0, 0, 35, 12, 1, 0, 0, 0, 36, 37, 7, 2, 0, 0, 37, 38, 1, 0, 0, 0, 38, 39, 6, 6, 0, 0, 39, 14, 1, 0, 0, 0, 3, 0, 31, 34, 1, 6, 0, 0] \ No newline at end of file diff --git a/src/PowerLexer.py b/src/PowerLexer.py new file mode 100644 index 0000000..400bfad --- /dev/null +++ b/src/PowerLexer.py @@ -0,0 +1,64 @@ +# Generated from arith.g4 by ANTLR 4.13.1 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + + +def serializedATN(): + return [ + 4,0,7,40,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2, + 6,7,6,1,0,1,0,1,1,1,1,1,2,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,5,5, + 5,30,8,5,10,5,12,5,33,9,5,3,5,35,8,5,1,6,1,6,1,6,1,6,0,0,7,1,1,3, + 2,5,3,7,4,9,5,11,6,13,7,1,0,3,1,0,49,57,1,0,48,57,3,0,9,10,13,13, + 32,32,41,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0, + 0,0,0,11,1,0,0,0,0,13,1,0,0,0,1,15,1,0,0,0,3,17,1,0,0,0,5,19,1,0, + 0,0,7,22,1,0,0,0,9,24,1,0,0,0,11,34,1,0,0,0,13,36,1,0,0,0,15,16, + 5,43,0,0,16,2,1,0,0,0,17,18,5,42,0,0,18,4,1,0,0,0,19,20,5,42,0,0, + 20,21,5,42,0,0,21,6,1,0,0,0,22,23,5,40,0,0,23,8,1,0,0,0,24,25,5, + 41,0,0,25,10,1,0,0,0,26,35,5,48,0,0,27,31,7,0,0,0,28,30,7,1,0,0, + 29,28,1,0,0,0,30,33,1,0,0,0,31,29,1,0,0,0,31,32,1,0,0,0,32,35,1, + 0,0,0,33,31,1,0,0,0,34,26,1,0,0,0,34,27,1,0,0,0,35,12,1,0,0,0,36, + 37,7,2,0,0,37,38,1,0,0,0,38,39,6,6,0,0,39,14,1,0,0,0,3,0,31,34,1, + 6,0,0 + ] + +class PowerLexer(Lexer): + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + T__0 = 1 + T__1 = 2 + T__2 = 3 + T__3 = 4 + T__4 = 5 + NUMBER = 6 + WS = 7 + + channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] + + modeNames = [ "DEFAULT_MODE" ] + + literalNames = [ "", + "'+'", "'*'", "'**'", "'('", "')'" ] + + symbolicNames = [ "", + "NUMBER", "WS" ] + + ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "NUMBER", "WS" ] + + grammarFileName = "arith.g4" + + def __init__(self, input=None, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.13.1") + self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) + self._actions = None + self._predicates = None + + diff --git a/src/PowerLexer.tokens b/src/PowerLexer.tokens new file mode 100644 index 0000000..d3047b4 --- /dev/null +++ b/src/PowerLexer.tokens @@ -0,0 +1,12 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +NUMBER=6 +WS=7 +'+'=1 +'*'=2 +'**'=3 +'('=4 +')'=5 diff --git a/src/arith-antlr.py b/src/arith-antlr.py new file mode 100644 index 0000000..fdec1f0 --- /dev/null +++ b/src/arith-antlr.py @@ -0,0 +1,17 @@ +# execute this script from src +# before using it, execute the following command: +# antlr4 -Dlanguage=Python3 arith.g4 + +# generated by the above antlr command (theoretically) +from arithLexer import arithLexer +from arithParser import arithParser +import antlr4 + +line = input('antlr-arith>> ') +while line != '': + input_stream = antlr4.InputStream(line) + lexer = arithLexer(input_stream) + token_stream = antlr4.CommonTokenStream(lexer) + parser = arithParser(token_stream) + context = parser.start() + line = input('>> ') diff --git a/src/arith.g4 b/src/arith.g4 new file mode 100644 index 0000000..605c833 --- /dev/null +++ b/src/arith.g4 @@ -0,0 +1,30 @@ +grammar arith; + +program: start+; + +start + :e=expr {print($e.r)} + ; + +expr returns [r] + :e=expr '+' p=prod {$r = $e.r + $p.r} + |p=prod {$r = $p.r} + ; + +prod returns [r] + :p=prod '*' pw=pow {$r = $p.r * $pw.r} + |pw=pow {$r = $pw.r} + ; + +pow returns [r] + :b=base '**' pw=pow {$r = $b.r ** $pw.r} + |b=base {$r = $b.r} + ; + +base returns [r] + :'('e= expr')' {$r = $e.r} + |n=NUMBER {$r = int($n.text)} + ; + +NUMBER: '0'|[1-9][0-9]*; +WS: [ \t\n\r] -> skip; diff --git a/src/arith.interp b/src/arith.interp new file mode 100644 index 0000000..e616ac4 --- /dev/null +++ b/src/arith.interp @@ -0,0 +1,31 @@ +token literal names: +null +'+' +'*' +'**' +'(' +')' +null +null + +token symbolic names: +null +null +null +null +null +null +NUMBER +WS + +rule names: +program +start +expr +prod +pow +base + + +atn: +[4, 1, 7, 68, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 1, 0, 4, 0, 14, 8, 0, 11, 0, 12, 0, 15, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 5, 2, 30, 8, 2, 10, 2, 12, 2, 33, 9, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 5, 3, 44, 8, 3, 10, 3, 12, 3, 47, 9, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 3, 4, 57, 8, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 66, 8, 5, 1, 5, 0, 2, 4, 6, 6, 0, 2, 4, 6, 8, 10, 0, 0, 66, 0, 13, 1, 0, 0, 0, 2, 17, 1, 0, 0, 0, 4, 20, 1, 0, 0, 0, 6, 34, 1, 0, 0, 0, 8, 56, 1, 0, 0, 0, 10, 65, 1, 0, 0, 0, 12, 14, 3, 2, 1, 0, 13, 12, 1, 0, 0, 0, 14, 15, 1, 0, 0, 0, 15, 13, 1, 0, 0, 0, 15, 16, 1, 0, 0, 0, 16, 1, 1, 0, 0, 0, 17, 18, 3, 4, 2, 0, 18, 19, 6, 1, -1, 0, 19, 3, 1, 0, 0, 0, 20, 21, 6, 2, -1, 0, 21, 22, 3, 6, 3, 0, 22, 23, 6, 2, -1, 0, 23, 31, 1, 0, 0, 0, 24, 25, 10, 2, 0, 0, 25, 26, 5, 1, 0, 0, 26, 27, 3, 6, 3, 0, 27, 28, 6, 2, -1, 0, 28, 30, 1, 0, 0, 0, 29, 24, 1, 0, 0, 0, 30, 33, 1, 0, 0, 0, 31, 29, 1, 0, 0, 0, 31, 32, 1, 0, 0, 0, 32, 5, 1, 0, 0, 0, 33, 31, 1, 0, 0, 0, 34, 35, 6, 3, -1, 0, 35, 36, 3, 8, 4, 0, 36, 37, 6, 3, -1, 0, 37, 45, 1, 0, 0, 0, 38, 39, 10, 2, 0, 0, 39, 40, 5, 2, 0, 0, 40, 41, 3, 8, 4, 0, 41, 42, 6, 3, -1, 0, 42, 44, 1, 0, 0, 0, 43, 38, 1, 0, 0, 0, 44, 47, 1, 0, 0, 0, 45, 43, 1, 0, 0, 0, 45, 46, 1, 0, 0, 0, 46, 7, 1, 0, 0, 0, 47, 45, 1, 0, 0, 0, 48, 49, 3, 10, 5, 0, 49, 50, 5, 3, 0, 0, 50, 51, 3, 8, 4, 0, 51, 52, 6, 4, -1, 0, 52, 57, 1, 0, 0, 0, 53, 54, 3, 10, 5, 0, 54, 55, 6, 4, -1, 0, 55, 57, 1, 0, 0, 0, 56, 48, 1, 0, 0, 0, 56, 53, 1, 0, 0, 0, 57, 9, 1, 0, 0, 0, 58, 59, 5, 4, 0, 0, 59, 60, 3, 4, 2, 0, 60, 61, 5, 5, 0, 0, 61, 62, 6, 5, -1, 0, 62, 66, 1, 0, 0, 0, 63, 64, 5, 6, 0, 0, 64, 66, 6, 5, -1, 0, 65, 58, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 66, 11, 1, 0, 0, 0, 5, 15, 31, 45, 56, 65] \ No newline at end of file diff --git a/src/arith.tokens b/src/arith.tokens new file mode 100644 index 0000000..d3047b4 --- /dev/null +++ b/src/arith.tokens @@ -0,0 +1,12 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +NUMBER=6 +WS=7 +'+'=1 +'*'=2 +'**'=3 +'('=4 +')'=5 diff --git a/src/arithLexer.interp b/src/arithLexer.interp new file mode 100644 index 0000000..9f6a130 --- /dev/null +++ b/src/arithLexer.interp @@ -0,0 +1,38 @@ +token literal names: +null +'+' +'*' +'**' +'(' +')' +null +null + +token symbolic names: +null +null +null +null +null +null +NUMBER +WS + +rule names: +T__0 +T__1 +T__2 +T__3 +T__4 +NUMBER +WS + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 7, 40, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 5, 5, 30, 8, 5, 10, 5, 12, 5, 33, 9, 5, 3, 5, 35, 8, 5, 1, 6, 1, 6, 1, 6, 1, 6, 0, 0, 7, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 1, 0, 3, 1, 0, 49, 57, 1, 0, 48, 57, 3, 0, 9, 10, 13, 13, 32, 32, 41, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 1, 15, 1, 0, 0, 0, 3, 17, 1, 0, 0, 0, 5, 19, 1, 0, 0, 0, 7, 22, 1, 0, 0, 0, 9, 24, 1, 0, 0, 0, 11, 34, 1, 0, 0, 0, 13, 36, 1, 0, 0, 0, 15, 16, 5, 43, 0, 0, 16, 2, 1, 0, 0, 0, 17, 18, 5, 42, 0, 0, 18, 4, 1, 0, 0, 0, 19, 20, 5, 42, 0, 0, 20, 21, 5, 42, 0, 0, 21, 6, 1, 0, 0, 0, 22, 23, 5, 40, 0, 0, 23, 8, 1, 0, 0, 0, 24, 25, 5, 41, 0, 0, 25, 10, 1, 0, 0, 0, 26, 35, 5, 48, 0, 0, 27, 31, 7, 0, 0, 0, 28, 30, 7, 1, 0, 0, 29, 28, 1, 0, 0, 0, 30, 33, 1, 0, 0, 0, 31, 29, 1, 0, 0, 0, 31, 32, 1, 0, 0, 0, 32, 35, 1, 0, 0, 0, 33, 31, 1, 0, 0, 0, 34, 26, 1, 0, 0, 0, 34, 27, 1, 0, 0, 0, 35, 12, 1, 0, 0, 0, 36, 37, 7, 2, 0, 0, 37, 38, 1, 0, 0, 0, 38, 39, 6, 6, 0, 0, 39, 14, 1, 0, 0, 0, 3, 0, 31, 34, 1, 6, 0, 0] \ No newline at end of file diff --git a/src/arithLexer.py b/src/arithLexer.py new file mode 100644 index 0000000..ecd5f9c --- /dev/null +++ b/src/arithLexer.py @@ -0,0 +1,64 @@ +# Generated from arith.g4 by ANTLR 4.13.1 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + + +def serializedATN(): + return [ + 4,0,7,40,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2, + 6,7,6,1,0,1,0,1,1,1,1,1,2,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,5,5, + 5,30,8,5,10,5,12,5,33,9,5,3,5,35,8,5,1,6,1,6,1,6,1,6,0,0,7,1,1,3, + 2,5,3,7,4,9,5,11,6,13,7,1,0,3,1,0,49,57,1,0,48,57,3,0,9,10,13,13, + 32,32,41,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0, + 0,0,0,11,1,0,0,0,0,13,1,0,0,0,1,15,1,0,0,0,3,17,1,0,0,0,5,19,1,0, + 0,0,7,22,1,0,0,0,9,24,1,0,0,0,11,34,1,0,0,0,13,36,1,0,0,0,15,16, + 5,43,0,0,16,2,1,0,0,0,17,18,5,42,0,0,18,4,1,0,0,0,19,20,5,42,0,0, + 20,21,5,42,0,0,21,6,1,0,0,0,22,23,5,40,0,0,23,8,1,0,0,0,24,25,5, + 41,0,0,25,10,1,0,0,0,26,35,5,48,0,0,27,31,7,0,0,0,28,30,7,1,0,0, + 29,28,1,0,0,0,30,33,1,0,0,0,31,29,1,0,0,0,31,32,1,0,0,0,32,35,1, + 0,0,0,33,31,1,0,0,0,34,26,1,0,0,0,34,27,1,0,0,0,35,12,1,0,0,0,36, + 37,7,2,0,0,37,38,1,0,0,0,38,39,6,6,0,0,39,14,1,0,0,0,3,0,31,34,1, + 6,0,0 + ] + +class arithLexer(Lexer): + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + T__0 = 1 + T__1 = 2 + T__2 = 3 + T__3 = 4 + T__4 = 5 + NUMBER = 6 + WS = 7 + + channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] + + modeNames = [ "DEFAULT_MODE" ] + + literalNames = [ "", + "'+'", "'*'", "'**'", "'('", "')'" ] + + symbolicNames = [ "", + "NUMBER", "WS" ] + + ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "NUMBER", "WS" ] + + grammarFileName = "arith.g4" + + def __init__(self, input=None, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.13.1") + self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) + self._actions = None + self._predicates = None + + diff --git a/src/arithLexer.tokens b/src/arithLexer.tokens new file mode 100644 index 0000000..d3047b4 --- /dev/null +++ b/src/arithLexer.tokens @@ -0,0 +1,12 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +NUMBER=6 +WS=7 +'+'=1 +'*'=2 +'**'=3 +'('=4 +')'=5 diff --git a/src/arithListener.py b/src/arithListener.py new file mode 100644 index 0000000..3732ff1 --- /dev/null +++ b/src/arithListener.py @@ -0,0 +1,66 @@ +# Generated from arith.g4 by ANTLR 4.13.1 +from antlr4 import * +if "." in __name__: + from .arithParser import arithParser +else: + from arithParser import arithParser + +# This class defines a complete listener for a parse tree produced by arithParser. +class arithListener(ParseTreeListener): + + # Enter a parse tree produced by arithParser#program. + def enterProgram(self, ctx:arithParser.ProgramContext): + pass + + # Exit a parse tree produced by arithParser#program. + def exitProgram(self, ctx:arithParser.ProgramContext): + pass + + + # Enter a parse tree produced by arithParser#start. + def enterStart(self, ctx:arithParser.StartContext): + pass + + # Exit a parse tree produced by arithParser#start. + def exitStart(self, ctx:arithParser.StartContext): + pass + + + # Enter a parse tree produced by arithParser#expr. + def enterExpr(self, ctx:arithParser.ExprContext): + pass + + # Exit a parse tree produced by arithParser#expr. + def exitExpr(self, ctx:arithParser.ExprContext): + pass + + + # Enter a parse tree produced by arithParser#prod. + def enterProd(self, ctx:arithParser.ProdContext): + pass + + # Exit a parse tree produced by arithParser#prod. + def exitProd(self, ctx:arithParser.ProdContext): + pass + + + # Enter a parse tree produced by arithParser#pow. + def enterPow(self, ctx:arithParser.PowContext): + pass + + # Exit a parse tree produced by arithParser#pow. + def exitPow(self, ctx:arithParser.PowContext): + pass + + + # Enter a parse tree produced by arithParser#base. + def enterBase(self, ctx:arithParser.BaseContext): + pass + + # Exit a parse tree produced by arithParser#base. + def exitBase(self, ctx:arithParser.BaseContext): + pass + + + +del arithParser \ No newline at end of file diff --git a/src/arithParser.py b/src/arithParser.py new file mode 100644 index 0000000..4a2816c --- /dev/null +++ b/src/arithParser.py @@ -0,0 +1,490 @@ +# Generated from arith.g4 by ANTLR 4.13.1 +# encoding: utf-8 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + +def serializedATN(): + return [ + 4,1,7,68,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,1,0,4,0, + 14,8,0,11,0,12,0,15,1,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,5,2,30,8,2,10,2,12,2,33,9,2,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3, + 1,3,5,3,44,8,3,10,3,12,3,47,9,3,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4, + 3,4,57,8,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,3,5,66,8,5,1,5,0,2,4,6,6, + 0,2,4,6,8,10,0,0,66,0,13,1,0,0,0,2,17,1,0,0,0,4,20,1,0,0,0,6,34, + 1,0,0,0,8,56,1,0,0,0,10,65,1,0,0,0,12,14,3,2,1,0,13,12,1,0,0,0,14, + 15,1,0,0,0,15,13,1,0,0,0,15,16,1,0,0,0,16,1,1,0,0,0,17,18,3,4,2, + 0,18,19,6,1,-1,0,19,3,1,0,0,0,20,21,6,2,-1,0,21,22,3,6,3,0,22,23, + 6,2,-1,0,23,31,1,0,0,0,24,25,10,2,0,0,25,26,5,1,0,0,26,27,3,6,3, + 0,27,28,6,2,-1,0,28,30,1,0,0,0,29,24,1,0,0,0,30,33,1,0,0,0,31,29, + 1,0,0,0,31,32,1,0,0,0,32,5,1,0,0,0,33,31,1,0,0,0,34,35,6,3,-1,0, + 35,36,3,8,4,0,36,37,6,3,-1,0,37,45,1,0,0,0,38,39,10,2,0,0,39,40, + 5,2,0,0,40,41,3,8,4,0,41,42,6,3,-1,0,42,44,1,0,0,0,43,38,1,0,0,0, + 44,47,1,0,0,0,45,43,1,0,0,0,45,46,1,0,0,0,46,7,1,0,0,0,47,45,1,0, + 0,0,48,49,3,10,5,0,49,50,5,3,0,0,50,51,3,8,4,0,51,52,6,4,-1,0,52, + 57,1,0,0,0,53,54,3,10,5,0,54,55,6,4,-1,0,55,57,1,0,0,0,56,48,1,0, + 0,0,56,53,1,0,0,0,57,9,1,0,0,0,58,59,5,4,0,0,59,60,3,4,2,0,60,61, + 5,5,0,0,61,62,6,5,-1,0,62,66,1,0,0,0,63,64,5,6,0,0,64,66,6,5,-1, + 0,65,58,1,0,0,0,65,63,1,0,0,0,66,11,1,0,0,0,5,15,31,45,56,65 + ] + +class arithParser ( Parser ): + + grammarFileName = "arith.g4" + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + sharedContextCache = PredictionContextCache() + + literalNames = [ "", "'+'", "'*'", "'**'", "'('", "')'" ] + + symbolicNames = [ "", "", "", "", + "", "", "NUMBER", "WS" ] + + RULE_program = 0 + RULE_start = 1 + RULE_expr = 2 + RULE_prod = 3 + RULE_pow = 4 + RULE_base = 5 + + ruleNames = [ "program", "start", "expr", "prod", "pow", "base" ] + + EOF = Token.EOF + T__0=1 + T__1=2 + T__2=3 + T__3=4 + T__4=5 + NUMBER=6 + WS=7 + + def __init__(self, input:TokenStream, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.13.1") + self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache) + self._predicates = None + + + + + class ProgramContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + def start(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(arithParser.StartContext) + else: + return self.getTypedRuleContext(arithParser.StartContext,i) + + + def getRuleIndex(self): + return arithParser.RULE_program + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterProgram" ): + listener.enterProgram(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitProgram" ): + listener.exitProgram(self) + + + + + def program(self): + + localctx = arithParser.ProgramContext(self, self._ctx, self.state) + self.enterRule(localctx, 0, self.RULE_program) + self._la = 0 # Token type + try: + self.enterOuterAlt(localctx, 1) + self.state = 13 + self._errHandler.sync(self) + _la = self._input.LA(1) + while True: + self.state = 12 + self.start() + self.state = 15 + self._errHandler.sync(self) + _la = self._input.LA(1) + if not (_la==4 or _la==6): + break + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + + class StartContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + self.e = None # ExprContext + + def expr(self): + return self.getTypedRuleContext(arithParser.ExprContext,0) + + + def getRuleIndex(self): + return arithParser.RULE_start + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterStart" ): + listener.enterStart(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitStart" ): + listener.exitStart(self) + + + + + def start(self): + + localctx = arithParser.StartContext(self, self._ctx, self.state) + self.enterRule(localctx, 2, self.RULE_start) + try: + self.enterOuterAlt(localctx, 1) + self.state = 17 + localctx.e = self.expr(0) + print(localctx.e.r) + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + + class ExprContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + self.r = None + self.e = None # ExprContext + self.p = None # ProdContext + + def prod(self): + return self.getTypedRuleContext(arithParser.ProdContext,0) + + + def expr(self): + return self.getTypedRuleContext(arithParser.ExprContext,0) + + + def getRuleIndex(self): + return arithParser.RULE_expr + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterExpr" ): + listener.enterExpr(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitExpr" ): + listener.exitExpr(self) + + + + def expr(self, _p:int=0): + _parentctx = self._ctx + _parentState = self.state + localctx = arithParser.ExprContext(self, self._ctx, _parentState) + _prevctx = localctx + _startState = 4 + self.enterRecursionRule(localctx, 4, self.RULE_expr, _p) + try: + self.enterOuterAlt(localctx, 1) + self.state = 21 + localctx.p = self.prod(0) + localctx.r = localctx.p.r + self._ctx.stop = self._input.LT(-1) + self.state = 31 + self._errHandler.sync(self) + _alt = self._interp.adaptivePredict(self._input,1,self._ctx) + while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: + if _alt==1: + if self._parseListeners is not None: + self.triggerExitRuleEvent() + _prevctx = localctx + localctx = arithParser.ExprContext(self, _parentctx, _parentState) + localctx.e = _prevctx + self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) + self.state = 24 + if not self.precpred(self._ctx, 2): + from antlr4.error.Errors import FailedPredicateException + raise FailedPredicateException(self, "self.precpred(self._ctx, 2)") + self.state = 25 + self.match(arithParser.T__0) + self.state = 26 + localctx.p = self.prod(0) + localctx.r = localctx.e.r + localctx.p.r + self.state = 33 + self._errHandler.sync(self) + _alt = self._interp.adaptivePredict(self._input,1,self._ctx) + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.unrollRecursionContexts(_parentctx) + return localctx + + + class ProdContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + self.r = None + self.p = None # ProdContext + self.pw = None # PowContext + + def pow_(self): + return self.getTypedRuleContext(arithParser.PowContext,0) + + + def prod(self): + return self.getTypedRuleContext(arithParser.ProdContext,0) + + + def getRuleIndex(self): + return arithParser.RULE_prod + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterProd" ): + listener.enterProd(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitProd" ): + listener.exitProd(self) + + + + def prod(self, _p:int=0): + _parentctx = self._ctx + _parentState = self.state + localctx = arithParser.ProdContext(self, self._ctx, _parentState) + _prevctx = localctx + _startState = 6 + self.enterRecursionRule(localctx, 6, self.RULE_prod, _p) + try: + self.enterOuterAlt(localctx, 1) + self.state = 35 + localctx.pw = self.pow_() + localctx.r = localctx.pw.r + self._ctx.stop = self._input.LT(-1) + self.state = 45 + self._errHandler.sync(self) + _alt = self._interp.adaptivePredict(self._input,2,self._ctx) + while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: + if _alt==1: + if self._parseListeners is not None: + self.triggerExitRuleEvent() + _prevctx = localctx + localctx = arithParser.ProdContext(self, _parentctx, _parentState) + localctx.p = _prevctx + self.pushNewRecursionContext(localctx, _startState, self.RULE_prod) + self.state = 38 + if not self.precpred(self._ctx, 2): + from antlr4.error.Errors import FailedPredicateException + raise FailedPredicateException(self, "self.precpred(self._ctx, 2)") + self.state = 39 + self.match(arithParser.T__1) + self.state = 40 + localctx.pw = self.pow_() + localctx.r = localctx.p.r * localctx.pw.r + self.state = 47 + self._errHandler.sync(self) + _alt = self._interp.adaptivePredict(self._input,2,self._ctx) + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.unrollRecursionContexts(_parentctx) + return localctx + + + class PowContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + self.r = None + self.b = None # BaseContext + self.pw = None # PowContext + + def base(self): + return self.getTypedRuleContext(arithParser.BaseContext,0) + + + def pow_(self): + return self.getTypedRuleContext(arithParser.PowContext,0) + + + def getRuleIndex(self): + return arithParser.RULE_pow + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterPow" ): + listener.enterPow(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitPow" ): + listener.exitPow(self) + + + + + def pow_(self): + + localctx = arithParser.PowContext(self, self._ctx, self.state) + self.enterRule(localctx, 8, self.RULE_pow) + try: + self.state = 56 + self._errHandler.sync(self) + la_ = self._interp.adaptivePredict(self._input,3,self._ctx) + if la_ == 1: + self.enterOuterAlt(localctx, 1) + self.state = 48 + localctx.b = self.base() + self.state = 49 + self.match(arithParser.T__2) + self.state = 50 + localctx.pw = self.pow_() + localctx.r = localctx.b.r ** localctx.pw.r + pass + + elif la_ == 2: + self.enterOuterAlt(localctx, 2) + self.state = 53 + localctx.b = self.base() + localctx.r = localctx.b.r + pass + + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + + class BaseContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + self.r = None + self.e = None # ExprContext + self.n = None # Token + + def expr(self): + return self.getTypedRuleContext(arithParser.ExprContext,0) + + + def NUMBER(self): + return self.getToken(arithParser.NUMBER, 0) + + def getRuleIndex(self): + return arithParser.RULE_base + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterBase" ): + listener.enterBase(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitBase" ): + listener.exitBase(self) + + + + + def base(self): + + localctx = arithParser.BaseContext(self, self._ctx, self.state) + self.enterRule(localctx, 10, self.RULE_base) + try: + self.state = 65 + self._errHandler.sync(self) + token = self._input.LA(1) + if token in [4]: + self.enterOuterAlt(localctx, 1) + self.state = 58 + self.match(arithParser.T__3) + self.state = 59 + localctx.e = self.expr(0) + self.state = 60 + self.match(arithParser.T__4) + localctx.r = localctx.e.r + pass + elif token in [6]: + self.enterOuterAlt(localctx, 2) + self.state = 63 + localctx.n = self.match(arithParser.NUMBER) + localctx.r = int((None if localctx.n is None else localctx.n.text)) + pass + else: + raise NoViableAltException(self) + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + + + def sempred(self, localctx:RuleContext, ruleIndex:int, predIndex:int): + if self._predicates == None: + self._predicates = dict() + self._predicates[2] = self.expr_sempred + self._predicates[3] = self.prod_sempred + pred = self._predicates.get(ruleIndex, None) + if pred is None: + raise Exception("No predicate with index:" + str(ruleIndex)) + else: + return pred(localctx, predIndex) + + def expr_sempred(self, localctx:ExprContext, predIndex:int): + if predIndex == 0: + return self.precpred(self._ctx, 2) + + + def prod_sempred(self, localctx:ProdContext, predIndex:int): + if predIndex == 1: + return self.precpred(self._ctx, 2) + + + + +