properly handle relop and fix switch cases

This commit is contained in:
Rusty Striker 2024-03-27 17:44:35 +02:00
parent b17f895f0a
commit ae2337376c
Signed by: RustyStriker
GPG key ID: 87E4D691632DFF15
4 changed files with 32 additions and 10 deletions

View file

@ -1,5 +1,5 @@
# Todo # Todo
- [ ] Error handling(so it wont just print sly: unexpected token or whatever it says) - [ ] Error handling(so it wont just print sly: unexpected token or whatever it says)
- [ ] Handle comparisons properly(==,!=,<=,>=,<,>)
- [ ] Proper readme about files - [ ] Proper readme about files
- [ ] Make cpq.py act as a cmd util - get input and output and such

13
cpq.py
View file

@ -18,11 +18,22 @@ a: int;
{ {
while(a < 10) { while(a < 10) {
a = a + 1; a = a + 1;
if(a == 5) if(a >= 6 || a == 5)
break; break;
else else
a = a + 0; a = a + 0;
} }
output(a);
switch(a * 5) {
case 1:
a = 5;
break;
case 5:
output(a);
default:
break;
}
output(a);
} }
''' '''

View file

@ -15,12 +15,12 @@ class Lexer(sly.Lexer):
literals = { '(', ')', '{', '}', ',', ':', ';', '=' } literals = { '(', ')', '{', '}', ',', ':', ';', '=' }
# define each token # define each token
RELOP = r'(==|!=|<|>|>=|<=)' RELOP = r'(==|!=|<=|>=|>|<)'
ADDOP = r'(\+|-)' ADDOP = r'(\+|-)'
MULOP = r'(\*|/)' MULOP = r'(\*|/)'
OR = '\|\|' OR = r'\|\|'
AND = '&&' AND = r'&&'
NOT = '!' NOT = r'!'
CAST = r'static_cast<(int|float)>' CAST = r'static_cast<(int|float)>'
ID = r'[a-zA-Z][a-zA-Z0-9]*' ID = r'[a-zA-Z][a-zA-Z0-9]*'

View file

@ -170,8 +170,13 @@ class Parser(sly.Parser):
self.lines[c.line + 1] = f'JMPZ {c.end} {cmp}' self.lines[c.line + 1] = f'JMPZ {c.end} {cmp}'
for b in c.breaks: for b in c.breaks:
self.lines[b] = break_line self.lines[b] = break_line
if len(cases) > 0:
last_case = cases[-1]
# modify the last jump(that skips over the next check) to not skip the default case
self.lines[last_case.end - 1] = f'JUMP {last_case.end}' # it is stupid, but an optimizer will hae no problem fixing it
for b in p[8].breaks: # breaks in default for b in p[8].breaks: # breaks in default
self.lines[b] = break_line self.lines[b] = break_line
return Statement([])
@_('caselist CASE NUM case_check ":" stmtlist') @_('caselist CASE NUM case_check ":" stmtlist')
@ -181,7 +186,8 @@ class Parser(sly.Parser):
self.had_errors = True self.had_errors = True
print_err(f'Invalid case constant at line {p.lineno}: Expected an integer but found a float') print_err(f'Invalid case constant at line {p.lineno}: Expected an integer but found a float')
# continue as if nothing happend # continue as if nothing happend
self.lines.append(f'JUMP {len(self.lines) + 2}') # Jump over the next comparison in the case of fallthrough self.lines.append(f'JUMP {len(self.lines) + 3}') # Jump over the next comparison in the case of fallthrough
line = p[3] line = p[3]
return p[0] + [ Case(p[2], line, len(self.lines), p[5].breaks) ] return p[0] + [ Case(p[2], line, len(self.lines), p[5].breaks) ]
@ -260,10 +266,15 @@ class Parser(sly.Parser):
new_term = self.next_temp() new_term = self.next_temp()
self.lines.append(f'ITOR {new_term} {rhs}') self.lines.append(f'ITOR {new_term} {rhs}')
rhs = new_term rhs = new_term
# TODO fix this and make it take care of all < > <= >= == != please yes thank you # RELOP to command map
command = ('R' if float_op else 'I') + ('ADD' if p[1] == '+' else 'SUB') com_map = { '<': 'LSS', '>': 'GRT', '==': 'EQL', '!=': 'NQL', '<=': 'GRT', '>=': 'LSS' }
# if we need to negate(since quad doesnt have a built in support for it)
should_negate = [ '<=', '>=' ]
command = ('R' if float_op else 'I') + com_map[p[1]]
result = self.next_temp() result = self.next_temp()
self.lines.append(f'{command} {result} {lhs} {rhs}') self.lines.append(f'{command} {result} {lhs} {rhs}')
if p[1] in should_negate:
self.lines.append(f'IEQL {result} {result} 0')
return Expression(result, False) return Expression(result, False)
@_('expression ADDOP term') @_('expression ADDOP term')