i dislike antlr

This commit is contained in:
Christoph J. Scherr 2023-12-17 20:32:03 +01:00
parent 1937279fec
commit 8ff9d89ee6
16 changed files with 991 additions and 3 deletions

View File

@ -1,3 +1,3 @@
antlr=4.13.1=ha770c72_0 antlr4-tools>=0.2.1
antlr4-tools=0.2.1=pypi_0 ply>=3.11
ply=3.11=py311h06a4308_0 antlr4-python3-runtime>=4.9

38
src/ArithLexer.interp Normal file
View File

@ -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]

64
src/ArithLexer.py Normal file
View File

@ -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 = [ "<INVALID>",
"'+'", "'*'", "'**'", "'('", "')'" ]
symbolicNames = [ "<INVALID>",
"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

12
src/ArithLexer.tokens Normal file
View File

@ -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

38
src/PowerLexer.interp Normal file
View File

@ -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]

64
src/PowerLexer.py Normal file
View File

@ -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 = [ "<INVALID>",
"'+'", "'*'", "'**'", "'('", "')'" ]
symbolicNames = [ "<INVALID>",
"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

12
src/PowerLexer.tokens Normal file
View File

@ -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

17
src/arith-antlr.py Normal file
View File

@ -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('>> ')

30
src/arith.g4 Normal file
View File

@ -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;

31
src/arith.interp Normal file
View File

@ -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]

12
src/arith.tokens Normal file
View File

@ -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

38
src/arithLexer.interp Normal file
View File

@ -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]

64
src/arithLexer.py Normal file
View File

@ -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 = [ "<INVALID>",
"'+'", "'*'", "'**'", "'('", "')'" ]
symbolicNames = [ "<INVALID>",
"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

12
src/arithLexer.tokens Normal file
View File

@ -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

66
src/arithListener.py Normal file
View File

@ -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

490
src/arithParser.py Normal file
View File

@ -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 = [ "<INVALID>", "'+'", "'*'", "'**'", "'('", "')'" ]
symbolicNames = [ "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>",
"<INVALID>", "<INVALID>", "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)