Init next project

This commit is contained in:
Jan-Niclas Loosen
2025-11-11 14:40:50 +01:00
parent edcf77fc18
commit fe33668b5f
43 changed files with 572 additions and 0 deletions

18
Project-02/main.py Normal file
View File

@@ -0,0 +1,18 @@
# This is a sample Python script for testing your TRIPLA parser.
# In PyCharm press Umschalt+F10 to execute it.
import triplayacc as yacc
import triplalex as lex
def test_parser(name):
source = "\n".join(open(name).readlines())
ast = yacc.parser.parse(source) # ,debug=True)
print("AST:")
print(ast)
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
test_parser('whileprograms/complex.while')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/

100
Project-02/parser.out Normal file
View File

@@ -0,0 +1,100 @@
Created by PLY version 3.11 (http://www.dabeaz.com/ply)
Grammar
Rule 0 S' -> expression
Rule 1 expression -> CONST
Rule 2 expression -> WHILE expression DO LBRACE expression RBRACE
Terminals, with rules where they appear
CONST : 1
DO : 2
LBRACE : 2
RBRACE : 2
WHILE : 2
error :
Nonterminals, with rules where they appear
expression : 2 2 0
Parsing method: LALR
state 0
(0) S' -> . expression
(1) expression -> . CONST
(2) expression -> . WHILE expression DO LBRACE expression RBRACE
CONST shift and go to state 2
WHILE shift and go to state 3
expression shift and go to state 1
state 1
(0) S' -> expression .
state 2
(1) expression -> CONST .
$end reduce using rule 1 (expression -> CONST .)
DO reduce using rule 1 (expression -> CONST .)
RBRACE reduce using rule 1 (expression -> CONST .)
state 3
(2) expression -> WHILE . expression DO LBRACE expression RBRACE
(1) expression -> . CONST
(2) expression -> . WHILE expression DO LBRACE expression RBRACE
CONST shift and go to state 2
WHILE shift and go to state 3
expression shift and go to state 4
state 4
(2) expression -> WHILE expression . DO LBRACE expression RBRACE
DO shift and go to state 5
state 5
(2) expression -> WHILE expression DO . LBRACE expression RBRACE
LBRACE shift and go to state 6
state 6
(2) expression -> WHILE expression DO LBRACE . expression RBRACE
(1) expression -> . CONST
(2) expression -> . WHILE expression DO LBRACE expression RBRACE
CONST shift and go to state 2
WHILE shift and go to state 3
expression shift and go to state 7
state 7
(2) expression -> WHILE expression DO LBRACE expression . RBRACE
RBRACE shift and go to state 8
state 8
(2) expression -> WHILE expression DO LBRACE expression RBRACE .
$end reduce using rule 2 (expression -> WHILE expression DO LBRACE expression RBRACE .)
DO reduce using rule 2 (expression -> WHILE expression DO LBRACE expression RBRACE .)
RBRACE reduce using rule 2 (expression -> WHILE expression DO LBRACE expression RBRACE .)

32
Project-02/parsetab.py Normal file
View File

@@ -0,0 +1,32 @@
# parsetab.py
# This file is automatically generated. Do not edit.
# pylint: disable=W,C,R
_tabversion = '3.10'
_lr_method = 'LALR'
_lr_signature = 'CONST DO LBRACE RBRACE WHILEexpression : CONSTexpression : WHILE expression DO LBRACE expression RBRACE'
_lr_action_items = {'CONST':([0,3,6,],[2,2,2,]),'WHILE':([0,3,6,],[3,3,3,]),'$end':([1,2,8,],[0,-1,-2,]),'DO':([2,4,8,],[-1,5,-2,]),'RBRACE':([2,7,8,],[-1,8,-2,]),'LBRACE':([5,],[6,]),}
_lr_action = {}
for _k, _v in _lr_action_items.items():
for _x,_y in zip(_v[0],_v[1]):
if not _x in _lr_action: _lr_action[_x] = {}
_lr_action[_x][_k] = _y
del _lr_action_items
_lr_goto_items = {'expression':([0,3,6,],[1,4,7,]),}
_lr_goto = {}
for _k, _v in _lr_goto_items.items():
for _x, _y in zip(_v[0], _v[1]):
if not _x in _lr_goto: _lr_goto[_x] = {}
_lr_goto[_x][_k] = _y
del _lr_goto_items
_lr_productions = [
("S' -> expression","S'",1,None,None,None),
('expression -> CONST','expression',1,'p_expression_const','triplayacc.py',28),
('expression -> WHILE expression DO LBRACE expression RBRACE','expression',6,'p_expression_while','triplayacc.py',33),
]

132
Project-02/syntax.py Normal file
View File

@@ -0,0 +1,132 @@
# (c) Stephan Diehl, University of Trier, Germany, 2025
class EXPRESSION:
ppcount=0
def __init__(self):
self.pp=EXPRESSION.ppcount
EXPRESSION.ppcount=EXPRESSION.ppcount+1
def copy(self):
return EXPRESSION()
def allNodes(self):
ret = [self]
for node in (self.__getattribute__(a) for a in self.__dict__.keys()):
if isinstance(node, EXPRESSION):
ret = ret + node.allNodes()
if isinstance(node, list):
for n in node:
if isinstance(n, EXPRESSION):
ret = ret + n.allNodes()
return ret
class LET(EXPRESSION):
def __init__(self, declarations, body):
super().__init__()
self.declarations=declarations
self.body=body
def __str__(self): return "let " \
+','.join([ str(decl) for decl in self.declarations ]) \
+ " in " + str(self.body)
class DECL(EXPRESSION):
def __init__(self, fname, params, body):
self.fname=fname
self.params=params
self.body=body
def __str__(self): return self.fname+"(" \
+','.join([ str(param) for param in self.params ]) \
+"){ "+str(self.body)+" }"
class CALL(EXPRESSION):
def __init__(self, fname, arguments):
super().__init__()
self.fname=fname
self.arguments=arguments
def __str__(self): return self.fname+"(" \
+','.join([ str(arg) for arg in self.arguments ]) +")"
class VAR(EXPRESSION):
def __init__(self,name):
super().__init__()
self.name=name
def __str__(self): return self.name
class BINOP(EXPRESSION):
def __init__(self,operator,arg1,arg2):
super().__init__()
self.operator=operator
self.arg1=arg1
self.arg2=arg2
def __str__(self): return "("+str(self.arg1)+self.operator+str(self.arg2)+")"
class CONST(EXPRESSION):
def __init__(self,value):
super().__init__()
self.value=value
def __str__(self): return str(self.value)
class ASSIGN(EXPRESSION):
def __init__(self, variable, expression):
super().__init__()
self.variable=variable
self.expression=expression
def __str__(self): return self.variable.name+"="+str(self.expression)
class SEQ(EXPRESSION):
def __init__(self, exp1, exp2):
super().__init__()
self.exp1=exp1
self.exp2=exp2
def __str__(self): return str(self.exp1)+";"+str(self.exp2)
class IF(EXPRESSION):
def __init__(self,condition,exp1,exp2):
super().__init__()
self.condition=condition
self.exp1=exp1
self.exp2=exp2
def __str__(self): return "if "+str(self.condition)+" then { " \
+ str(self.exp1)+" } else { "+str(self.exp2)+" } "
class DO(EXPRESSION):
def __init__(self,body,condition):
super().__init__()
self.body=body
self.condition=condition
def __str__(self): return "do { "+str(self.body)+" } while "+str(self.condition)
class WHILE(EXPRESSION):
def __init__(self,condition,body):
super().__init__()
self.condition=condition
self.body=body
def __str__(self): return "while "+str(self.condition)+" do { "+str(self.body)+" }"
# see https://stackoverflow.com/questions/51753937/python-pretty-print-nested-objects
def pretty_print(clas, indent=0):
print(' ' * indent + type(clas).__name__ + ':')
indent += 4
for k,v in clas.__dict__.items():
if '__dict__' in dir(v):
pretty_print(v,indent)
else:
print(' ' * indent + k + ': ' + str(v))

46
Project-02/triplalex.py Normal file
View File

@@ -0,0 +1,46 @@
# ------------------------------------------------------------
# triplalex.py
#
# tokenizer for the TRIPLA parser
# ------------------------------------------------------------
import ply.lex as lex
reserved = {
'while' : 'WHILE',
'do' : 'DO',
}
# List of token names. This is always required
tokens = [
'CONST',
'LBRACE', 'RBRACE'
]+list(reserved.values())
# Regular expression rules for simple tokens
t_LBRACE = r'\{'
t_RBRACE = r'\}'
t_WHILE = r'while'
t_DO = r'do'
# A regular expression rule with some action code
def t_CONST(t):
r'\d+'
t.value = int(t.value)
return t
# Define a rule so we can track line numbers
def t_newline(t):
r'\n+'
t.lexer.lineno += len(t.value)
# A string containing ignored characters (spaces and tabs)
t_ignore = ' \t'
# Error handling rule
def t_error(t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
# Build the lexer
lexer = lex.lex()

View File

@@ -0,0 +1,2 @@
let a(x,y,z) {x}
in a(1,2,3)

View File

@@ -0,0 +1,15 @@
let
f1(b) {
if(b==0) then 0 else f1(b-1)
}
f2(a, b) {
if(a > b) then f1(a) else f1(b);
let g(c) {
a*b*c
} in g(a*b)
}
in
f1(10); f2(10, let max(a, b) {
if(a > b) then a else b
}
in max(20, 30))

View File

@@ -0,0 +1 @@
if 2 < x && x > 9 then 1 else 0

View File

@@ -0,0 +1,4 @@
let a(x) {x}
b(y) {y}
c(z) {z}
in a(1); b(2); c(3)

View File

@@ -0,0 +1,38 @@
let
fac(x) {
if (x == 1) then 1
else fac(x-1)*x
}
fac(x) {
if (x == 1) then 1
else fac(x-1)*x
}
fac(x) {
if (x == 1) then 1
else fac(x-1)*x
}
fac(x) {
if (x == 1) then 1
else fac(x-1)*x
}
fac(x) {
if (x == 1) then 1
else fac(x-1)*x
}
fac(x) {
if (x == 1) then 1
else fac(x-1)*x
}
fac(x) {
if (x == 1) then 1
else fac(x-1)*x
}
fac(x) {
if (x == 1) then 1
else fac(x-1)*x
}
fac(x) {
if (x == 1) then 1
else fac(x-1)*x
}
in fac(3)

View File

@@ -0,0 +1 @@
let n(a) {a} in n(5) + m(5) ; let m(a) {a+1} in m(5)

View File

@@ -0,0 +1 @@
if (2 && 7 > 2) then 1 else 0

View File

@@ -0,0 +1,7 @@
let func(a,b) {
do {
b = b + 1;
a = a - 1
} while ( a > 0 && b != a )
}
in func(10, 8)

View File

@@ -0,0 +1,12 @@
let ggT(a, b) {
if (a == b) then
a
else
do {
if (a > b) then
a = a - b
else
b = b - a
} while (a != b);
a
} in ggT(3528, 3780) // result should be 252

View File

@@ -0,0 +1,8 @@
let ggT(a, b) {
if (a == b) then
a
else if (a > b) then
ggT(a-b, b)
else
ggT(b-a, a)
} in ggT(3528, 3780) // result should be 252

View File

@@ -0,0 +1,3 @@
let f1(b) { if (b == 0) then 0 else f1(b-1) }
f2(a,b) { if (a > b) then f1(a) else f1(b) }
in f1(10); f2(10,-20)

View File

@@ -0,0 +1 @@
let m(a){a} in m(5);let m(b){b+1} in m(5)

View File

@@ -0,0 +1 @@
let n(a) {a} in n(5) ; let m(a) {a+1} in n(5) + m(5)

View File

@@ -0,0 +1 @@
if(true||true==true) then 1 else 0

View File

@@ -0,0 +1,3 @@
let g(a) {
a*a
} in g(5)

View File

@@ -0,0 +1,9 @@
let f1(b) {
if (b==0) then 0 else f1(b-1)
} in f1(10)
/*
f2(a,b) {
if (a>b) then f1(a) else f1(b)
}
in f1(10); f2(10,20)
*/

View File

@@ -0,0 +1,14 @@
let f1(b) {
if (b==0) then 0 else f1(b-1)
}
f2(a,b) {
if (a>b) then f1(a) else f1(b);
let g(c) {
a*b*c
}
in g(a*b)
}
in f1(10); f2(10, let max(a,b) {
if (a>b) then a else b
}
in max(20,30) )

View File

@@ -0,0 +1,4 @@
let func(a,b) {
a = b + 1
}
in func(10, 8)

View File

@@ -0,0 +1,9 @@
let func(a, b) {
let func(a, b) {
a * b
} in
do {
b = b + 1 * func(3, 1);
a = a - 1
} while ( a > 0 && b != a )
} in func(10, 8)

View File

@@ -0,0 +1,13 @@
let f(a, b) {
if (a == 0) then
2 + b
else
let g(a, c) {
a + c + b
} in 2 + g(a, b)
} g(c, d) {
if (c == 0) then
1 + d
else
c * f(c - 1, d)
} in f (2, 3); g (3, 2)

View File

@@ -0,0 +1,5 @@
let f(x, y) {
let g(x) {
y = x + 7
} in x = g(5); y
} in f(1, 2)

View File

@@ -0,0 +1,4 @@
let g(x, y) {
y = 3;
x
} in g(2)

View File

@@ -0,0 +1 @@
if (true) then 1 else 0

View File

@@ -0,0 +1 @@
if (true && false) then 1 else 0

View File

@@ -0,0 +1 @@
if (true || false) then 1 else 0

View File

@@ -0,0 +1 @@
if (1 > 2) then 1 else 0

View File

@@ -0,0 +1 @@
if (2 > 3 + 5) then 1 else 0

View File

@@ -0,0 +1 @@
if (1 > 2 || 3 < 5) then 1 else 0

View File

@@ -0,0 +1 @@
if (2 == 0 == false) then 1 else 0

View File

@@ -0,0 +1,2 @@
let square(x) { x*x }
in square(10)

View File

@@ -0,0 +1,4 @@
let mult(a,b) { a*b }
add(a,b) { let inc(a) { if (b!=0) then b=b-1;inc(a+1) else mult(a,1) }
in inc(a) }
in add(mult(2,3),add(4,5))

View File

@@ -0,0 +1,7 @@
let func(a,b) {
while ( a > 0 && b != a ) do {
b = b + 1;
a = a - 1
}
}
in func(10, 8)

View File

@@ -0,0 +1,3 @@
while (true) do {
3
}

View File

@@ -0,0 +1,8 @@
let wrapper(a, b) {
let ggt(noneSense) {
if a == b then a
else
if a > b then wrapper(a-b, b)
else wrapper(b-a, a)
} in ggt(0)
} in wrapper(21, 49)

View File

@@ -0,0 +1,9 @@
let wrapper(number, threshold) {
let square(x) {
if x*x > threshold
then x
else x*x
}
in square(number)
}
in wrapper(4, 10)

45
Project-02/triplayacc.py Normal file
View File

@@ -0,0 +1,45 @@
# ------------------------------------------------------------
# triplayacc.py
#
# Yacc grammar of the TRIPLA language
''' Here an initial grammar
E -> while E do { E }
| CONST
CONST: Positive, integer numbers = 0 | [1-9][0-9]*
'''
# Note: For LALR(1) left recursion is preferred
# ------------------------------------------------------------
import ply.yacc as yacc
import syntax as ast
# Get the token map from the lexer. This is required.
from triplalex import tokens
precedence = (
)
def p_expression_const(p):
'expression : CONST'
p[0] = ast.CONST(p[1])
def p_expression_while(p):
'expression : WHILE expression DO LBRACE expression RBRACE'
p[0] = ast.WHILE(p[2],p[5])
#def p_empty(p):
# 'empty :'
# pass
# Error rule for syntax errors
def p_error(p):
print("Syntax error in input!")
# Build the parser
parser = yacc.yacc() # debug=True

View File

@@ -0,0 +1,2 @@
while while 1 do { 2 }
do { while 3 do { 4 } }

View File

@@ -0,0 +1 @@
while 1 do { 2 }