Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • theo.putegnat/infosec-ecomp
  • damien.armillon/infosec-ecomp
  • mouhamed.sougou/infosec-ecomp
  • cidre-public/compilation/infosec-ecomp
4 results
Show changes
Showing
with 612 additions and 238 deletions
SYM_STRUCT
SYM_IDENTIFIER(S)
SYM_LBRACE
SYM_INT
SYM_IDENTIFIER(t)
SYM_LBRACKET
SYM_INTEGER(4)
SYM_RBRACKET
SYM_SEMICOLON
SYM_RBRACE
SYM_SEMICOLON
SYM_INT
SYM_IDENTIFIER(main)
SYM_LPARENTHESIS
SYM_RPARENTHESIS
SYM_LBRACE
SYM_STRUCT
SYM_IDENTIFIER(S)
SYM_IDENTIFIER(s)
SYM_SEMICOLON
SYM_LPARENTHESIS
SYM_IDENTIFIER(s)
SYM_POINT
SYM_IDENTIFIER(t)
SYM_RPARENTHESIS
SYM_LBRACKET
SYM_INTEGER(0)
SYM_RBRACKET
SYM_ASSIGN
SYM_INTEGER(1)
SYM_SEMICOLON
SYM_IDENTIFIER(print_int)
SYM_LPARENTHESIS
SYM_LPARENTHESIS
SYM_IDENTIFIER(s)
SYM_POINT
SYM_IDENTIFIER(t)
SYM_RPARENTHESIS
SYM_LBRACKET
SYM_INTEGER(0)
SYM_RBRACKET
SYM_RPARENTHESIS
SYM_SEMICOLON
SYM_RETURN
SYM_LPARENTHESIS
SYM_IDENTIFIER(s)
SYM_POINT
SYM_IDENTIFIER(t)
SYM_RPARENTHESIS
SYM_LBRACKET
SYM_INTEGER(0)
SYM_RBRACKET
SYM_SEMICOLON
SYM_RBRACE
SYM_EOF
#!/usr/bin/python3
import argparse, glob
"""Test orchestration for ecomp"""
import argparse
import glob
from threading import Thread
import subprocess
import json
from subprocess import *
from subprocess import Popen, PIPE
import signal
import sys
import time
import textwrap
import numpy as np
import difflib
parser = argparse.ArgumentParser()
parser.add_argument("-f", "--file",
help="files to compile",
default=glob.glob("*.e"),
nargs='+')
parser.add_argument("-p", "--passes",
help="passes to execute",
nargs='+',
default=["e-run",
"cfg-run",
"cfg-run-after-cp",
"cfg-run-after-dae",
"cfg-run-after-ne",
"rtl-run",
"linear-run",
"linear-run-after-dse",
"ltl-run",
"riscv-run"])
parser.add_argument("--args",
help="args for programs",
nargs='+',
default=["14","12","3","8","12"])
parser.add_argument("--html", help="Output HTML file",
default="results.html")
parser.add_argument("-d", "--dry-run", help="Dry-run. Don't actually compile anything",
action="store_true")
parser.add_argument("-v", "--verbose", help="Verbosity level",
action="count", default=0)
parser.add_argument("--make-expect", help="Make .expect files for each test",
action="store_true")
args,unknown_args = parser.parse_known_args()
# show options
if(args.verbose >= 1):
print("args.file=" + str(args.file))
print("args.passes=" + str(args.passes))
print("args.args=" + str(args.args))
print("args.html=" + str(args.html))
print("args.dry_run=" + str(args.dry_run))
print("args.verbose=" + str(args.verbose))
# construct the set of commands to be launched, one per file
cmds = []
for f in args.file:
cmd = "../main.native -json -f {} {} {} -- {}".format(f,
" ".join(map(lambda s : "-"+s, args.passes)),
" ".join(unknown_args),
" ".join(args.args)
)
cmds.append((f,cmd))
# dyr_run : simply show the commands but don't execute them
if args.dry_run:
for (f,cmd) in cmds:
print(cmd)
exit()
# The list of threads that will be launched
threads = []
from typing import List
import datetime
# The displayer thread shows what commands are still running
class Displayer(Thread):
def __init__(self):
"""A Displayer thread"""
def __init__(self, threads):
Thread.__init__(self)
self.threads = threads
def run(self):
width = 120
l = [x for x in threads if x.running]
while len(l):
s = "{} threads running ".format(len(l))
thrs = str(list(map(lambda x: x.f, l)))[:(width-len(s))]
print("\r{}({}).{}".format(s, thrs, " "*(width-len(thrs) - len(s))), end="")
l_running = [x for x in self.threads if x.running]
while len(l_running) > 0:
s_running = "{} threads running ".format(len(l_running))
thrs = str(list(map(lambda x: x.filename,
l_running)))[:(width - len(s_running))]
print("\r{}({}).{}".format(
s_running, thrs, " " * (width - len(thrs) - len(s_running))),
end="")
time.sleep(1)
l = [x for x in threads if x.running]
l_running = [x for x in self.threads if x.running]
print()
# The number of columns in the HTML table
numcols = len(args.passes)
def display_verbatim(body):
return '\n'.join(['\n'.join(textwrap.wrap(line, 90,
break_long_words=False, replace_whitespace=False))
for line in body.splitlines() if line.strip() != ''])
"Show verbatim contents"
return '\n'.join([
'\n'.join(
textwrap.wrap(line,
90,
break_long_words=False,
replace_whitespace=False))
for line in body.splitlines() if line.strip() != ''
])
def make_td(td):
"Create a TD HTML tag"
if isinstance(td, list):
text = td[0]
opts = " ".join(td[1:])
......@@ -103,16 +59,18 @@ def make_td(td):
text = str(td)
opts = ""
return "<td {}>{}</td>".format(opts,text)
return "<td {}>{}</td>".format(opts, text)
def make_table_row(tds):
return "<tr>\n" + "".join(map(make_td,tds)) + "</tr>\n"
icon_ok = "<i class='fa fa-check' style='color: green;'></i>"
icon_warn = "<i class='fa fa-exclamation-circle' style='color: orange;'></i>"
icon_ko = "<i class='fa fa-times-circle' style='color:red;'></i>"
# CommandExecutor run a command [cmd] and operates on file [f]
class CommandExecutor(Thread):
def __init__(self, f, cmd):
"""Command Executor"""
def __init__(self, filename, cmd, args, make_expect, numcols):
Thread.__init__(self)
self.f = f
self.filename = filename
self.cmd = cmd
self.s = ""
self.running = True
......@@ -120,201 +78,362 @@ class CommandExecutor(Thread):
self.stderr = ""
self.lastcorrectstep = -1
self.proc = None
self.args = args
self.make_expect = make_expect
self.numcols = numcols
# run cmd and get stdout and stderr in dict
def run_capture_output_interruptible(self,cmd):
process = Popen(cmd, stdout=PIPE, stderr=PIPE)
self.proc = process
def run_capture_output_interruptible(self, cmd):
self.proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
try:
stdout, stderr = process.communicate()
retcode = process.poll()
return {'stdout' : stdout, 'stderr': stderr}
self.stdout, self.stderr = self.proc.communicate()
self.proc.poll()
self.stdout = self.stdout.decode('utf8')
self.stderr = self.stderr.decode('utf8')
except:
return {'stdout' : b"[]", 'stderr': ""}
self.stdout = (b"[]").decode('utf8')
self.stderr = "".decode('utf8')
def stop(self):
"""Stop the thread"""
if self.proc:
self.proc.kill()
def run(self):
c = self.cmd.split(" ")
process = self.run_capture_output_interruptible(c)
self.stdout = process['stdout'].decode('utf8')
self.stderr = process['stderr'].decode('utf8')
j = []
def get_test_results(self, json_file_name):
"Get test results, handle errors"
try:
j = json.loads(self.stdout)
with open(json_file_name, 'r') as jsonfile:
try:
return json.load(jsonfile)
except:
return [{
'retval': -1,
'output': display_verbatim(self.stdout),
'error': display_verbatim(self.stderr)
}]
except:
return [{
'retval': -1,
'output': display_verbatim(self.stdout),
'error': "No file {} generated...".format(json_file_name)
}]
@staticmethod
def register_expect(expect_file_name, out, err, ret):
"Creates a .expect file"
with open(expect_file_name, 'w') as expectfile:
json.dump(
{
'output': out,
'error': err,
'retval': ret
}, expectfile)
@staticmethod
def check_expect(expect_file_name, out, err, ret):
"Checks a result wrt an expect file"
try:
with open(expect_file_name, 'r') as expectfile:
j = json.load(expectfile)
return j['retval'] == ret and \
j['output'] == out and \
j['error'] == err
except:
j.append({'retval':-1,
'output': display_verbatim(self.stdout),
'error': display_verbatim(self.stderr)})
old_ret = None
old_out = None
old_err = None
return None
def run(self):
"""Actually run the test"""
self.run_capture_output_interruptible(self.cmd.split(" "))
json_file_name = self.filename + ".json"
j = self.get_test_results(json_file_name)
self.s = ""
curcol = 0
numrunstep = 0
for i, r in enumerate(j, start=0):
first_runstep = True
for _, r in enumerate(j, start=0):
if "runstep" in r:
expect_file_name = self.f + ".expect_" + "_".join(args.args)
if numrunstep == 0:
if args.make_expect:
with open(expect_file_name, 'w') as expectfile:
json.dump({ 'output' : r['output'],
'error' : r['error'],
'retval': r['retval']}, expectfile)
numrunstep = numrunstep + 1
if old_ret == None:
old_ret = r['retval']
if old_out == None: old_out = r['output']
if old_err == None: old_err = r['error']
expect_file_name = self.filename + ".expect_" + "_".join(self.args)
if first_runstep and self.make_expect:
self.register_expect(expect_file_name, r['output'], r['error'], r['retval'])
first_runstep = False
cls = "good"
try:
with open(expect_file_name, 'r') as expectfile:
j = json.load(expectfile)
if j['retval'] == r['retval'] and j['output'] == r['output'] and j['error'] == r['error']:
cls = "good"
else:
cls = "bad"
except:
test_ok = self.check_expect(expect_file_name, r['output'], r['error'], r['retval'])
if test_ok is None:
cls = ""
else:
cls = "good" if test_ok else "bad"
if cls == "good":
self.lastcorrectstep = curcol
self.s += make_td(["Ret = {}.<br>Output = <pre>'{}'</pre>{}".
format(r['retval'], r['output'],
"Error: "+r['error'] if r['error'] != None else ""),
"class=\"{}\"".format(cls)])
curcol+=1
err_str = "Error: <pre>" + r['error'] + "</pre>" if r['error'] is not None else ""
self.s += make_td([
"{}<div name='{}' style='display:none;'>Ret = {}.<br>Output = <pre>'{}'</pre>{}<br>Time: {:.2f} seconds.</div>"
.format(
icon_ok if cls == 'good' else icon_ko,
self.filename,
r['retval'],
r['output'],
err_str,
r['time']),
"class=\"{}\"".format(cls)
]) + "\n"
curcol += 1
elif "compstep" in r:
compstep_td = ""
err = r['error']
if err != None:
compstep_td="""
<td class="bad" style="text-align: left;" colspan="{}">{} error:<br><pre>{}</pre></td>
""".format( numcols - curcol, r['compstep'],err)
self.s += compstep_td
break
if err is not None:
compstep_td = """
<td class="bad" style="text-align: left;" colspan="{}">{}<div name='{}' style='display:none'>{} error:<br><pre>{}</pre></div></td>
""".format(self.numcols - curcol,
icon_ko,
self.filename,
r['compstep'], err)
elif r["compstep"] == "Parsing":
compstep_td = """
<td class="good">{}</td>
""".format(icon_ok)
elif r["compstep"] == "Lexing":
expect_lex_file_name = self.f + ".expect_lexer"
out_lex_file_name = self.f[:-2] + ".lex"
expect_lex_file_name = self.filename + ".expect_lexer"
out_lex_file_name = self.filename[:-2] + ".lex"
try:
with open(expect_lex_file_name, "r") as expect_lex_file, open(out_lex_file_name, "r") as out_lex_file:
with open(expect_lex_file_name, "r") as expect_lex_file, \
open(out_lex_file_name, "r") as out_lex_file:
expected_tokens = expect_lex_file.readlines()
out_tokens = out_lex_file.readlines()
diff = difflib.unified_diff(expected_tokens, out_tokens,
fromfile=expect_lex_file_name,
tofile=out_lex_file_name)
diff = difflib.unified_diff(
expected_tokens,
out_tokens,
fromfile=expect_lex_file_name,
tofile=out_lex_file_name)
diff = list(diff)
if diff == []:
compsted_td = ""
compstep_td = "<td class=\"good\">{}</td>".format(icon_ok)
else:
compstep_td = "<td class=\"bad\" style=\"text-align: left;\" colspan=\"{}\">{} not-what-expected:<br><pre>".format( numcols - curcol, r['compstep'])
for line in diff:
compstep_td += line
compstep_td += "{}</pre></td>"
self.s += compstep_td
break
compstep_td = "<td class=\"warn\" style=\"text-align: left;\" >{}<div name='{}'>Lexing not-what-expected:<br><pre>{}</pre></div></td>".format(icon_warn, self.filename, "".join(diff))
except:
compstep_td = ""
compstep_td = "<td>No .expect_lexer file</td>"
self.s += compstep_td
self.s += compstep_td + "\n"
else:
err = r['error']
if err != None:
self.s +="""
if err is not None:
self.s += """
<td class="bad" style="text-align: left;" colspan="{}">error:<br><pre>{}</pre></td>
""".format( numcols - curcol, err)
""".format(self.numcols - curcol, err) + "\n"
else:
self.s +="""
self.s += """
<td class="bad" colspan="{}">error:<br><pre>{}</pre></td>
""".format( numcols - curcol, r)
self.s = """<tr><td class="rowname"><a href="{}.html">{}</a></td>{}</tr>""".format(self.f,self.f,self.s)
self.running = False
""".format(self.numcols - curcol, r) + "\n"
def interrupt_handler(sig, frame):
print('You pressed Ctrl+C!')
for t in threads:
t.stop()
signal.signal(signal.SIGINT, interrupt_handler)
for (f,cmd) in cmds:
t = CommandExecutor(f, cmd)
threads.append(t)
t.start()
d = Displayer()
d.start()
for t in threads:
t.join()
d.join()
print ("All threads terminated!")
res_html = open(args.html, "w")
res_html.write("""
<style type="text/css">
table , table th, table td , table tr{
border: 1px solid black;
border-collapse: collapse;
text-align: center;
}
.rowname, th {
background-color: #ccc;
}
td {
padding: 0.4em;
}
.bad{
background-color: #f9d7dc;
}
.good{
background-color: #c7f0d2;
}
fieldset {
display: inline;
margin: 1em;
padding: 1em;
}
</style>
<table>
self.s = """
<tr>
<th>File</th>""")
for p in args.passes:
res_html.write("<th>{}</th>\n".format(p))
res_html.write("""
</tr>
""")
def k(t):
return (t.lastcorrectstep,t.f)
threads = sorted(threads, key=k, reverse=False)
<td class="rowname">
<a href="{}.html">{}</a>
<input class="w3-btn" id='toggle{}' type="button" onclick="toggle('{}')" value="+"/>
</td>
{}
</tr>""".format(self.filename, self.filename,
self.filename, self.filename, self.s) + "\n"
for t in threads:
res_html.write(t.s)
res_html.close()
numtotal = len(threads)
ok = [t for t in threads if t.lastcorrectstep == numcols-1]
ko = [t for t in threads if t.lastcorrectstep != numcols-1]
print("{}/{} OK.".format(len(ok), numtotal))
print("{}/{} KO : {}".format(len(ko), numtotal,list(map((lambda t: (t.f, t.lastcorrectstep)), ko))))
self.running = False
if args.verbose >= 1:
for t in ko + (ok if args.verbose >= 2 else []):
print(t.f)
print("STDOUT: \n{}".format(t.stdout))
print("STDERR: \n{}".format(t.stderr))
def interrupt_handler(threads):
"Interrupt handler"
def int_handler(_sig, _frame):
"Interrupt handler"
print('You pressed Ctrl+C!')
for thr in threads:
thr.stop()
return int_handler
def get_args():
"Get arguments"
parser = argparse.ArgumentParser()
parser.add_argument("-f",
"--file",
help="files to compile",
default=glob.glob("*.e"),
nargs='+')
parser.add_argument("-p",
"--passes",
help="passes to execute",
nargs='+',
default=[
"e-run", "cfg-run", "cfg-run-after-cp",
"cfg-run-after-dae", "cfg-run-after-ne", "rtl-run",
"linear-run", "linear-run-after-dse", "ltl-run",
"riscv-run"
])
parser.add_argument("--args",
help="args for programs",
nargs='+',
default=["14", "12", "3", "8", "12"])
parser.add_argument("--html", help="Output HTML file", default="results.html")
parser.add_argument("-d",
"--dry-run",
help="Dry-run. Don't actually compile anything",
action="store_true")
parser.add_argument("-v",
"--verbose",
help="Verbosity level",
action="count",
default=0)
parser.add_argument("--make-expect",
help="Make .expect files for each test",
action="store_true")
args, unknown_args = parser.parse_known_args()
return args, unknown_args
def main():
"Main function"
args, unknown_args = get_args()
# show options
if args.verbose >= 1:
print("args.file=" + str(args.file))
print("args.passes=" + str(args.passes))
print("args.args=" + str(args.args))
print("args.html=" + str(args.html))
print("args.dry_run=" + str(args.dry_run))
print("args.verbose=" + str(args.verbose))
# construct the set of commands to be launched, one per file
cmds = []
for fname in args.file:
cmd = "../ecomp -json {f}.json -f {f} {passes} {uargs} -- {args}"
cmd = cmd.format(passes=" ".join(map(lambda s: "-" + s, args.passes)),
uargs=" ".join(unknown_args),
args=" ".join(args.args),
f=fname)
cmds.append((fname, cmd))
# dyr_run : simply show the commands but don't execute them
if args.dry_run:
for (_, cmd) in cmds:
print(cmd)
sys.exit()
# The list of threads that will be launched
threads: List[Thread] = []
signal.signal(signal.SIGINT, interrupt_handler(threads))
for (fname, cmd) in cmds:
exec_thread = CommandExecutor(fname, cmd,
args.args, args.make_expect,
# 1 colonne pour le lexer
# 1 colonne pour le parser
len(args.passes) + 2)
threads.append(exec_thread)
exec_thread.start()
print("Before launching displayer: {} threads".format(len(threads)))
disp_thread = Displayer(list(threads))
disp_thread.start()
for thr in threads:
thr.join()
disp_thread.join()
print("After displayer: {} threads".format(len(threads)))
print("All threads terminated!")
res_html = open(args.html, "w")
res_html.write("""
<html>
<head>
<link rel="stylesheet" href="w3.css">
<script src="https://kit.fontawesome.com/1f5d81749b.js" crossorigin="anonymous"></script>
<style type="text/css">
/*
table , table th, table td , table tr{
border: 1px solid black;
border-collapse: collapse;
text-align: center;
}
.rowname, th {
background-color: #ccc;
}
td {
padding: 0.4em;
}
.bad{
background-color: #f9d7dc;
}
.good{
background-color: #c7f0d2;
}
.warn{
background-color: orange;
}
fieldset {
display: inline;
margin: 1em;
padding: 1em;
}*/
</style>
<script type="text/javascript">
function toggleVisibility(elt){
if (elt.style.display == 'none')
elt.style.display = 'block';
else
elt.style.display = 'none';
}
function toggle(name){
var elts = document.getElementsByName(name);
console.log(elts);
for (var k = 0; k < elts.length; k++){
toggleVisibility(elts[k]);
}
var x = document.getElementById('toggle'+name);
if (x.value == '+') x.value = '-';
else x.value = '+';
}
</script>
</head>
<body>""")
now = datetime.datetime.now()
res_html.write ("{}".format(now))
res_html.write("""
<table class="w3-table w3-striped w3-responsive">
<tr><th>File</th>""")
for pass_name in ["Lexer","Parser"] + args.passes:
res_html.write("<th style='transform: rotate(180deg); writing-mode: vertical-rl;'>{}</th>\n".format(pass_name))
res_html.write("""
</tr>
""")
print("Before sorting: {} threads".format(len(threads)))
threads = sorted(threads, key=lambda t: (t.lastcorrectstep, t.filename), reverse=False)
print("After sorting: {} threads".format(len(threads)))
for thr in threads:
res_html.write(thr.s)
res_html.write("\n")
res_html.write("</table>\n")
res_html.write("</body>\n")
res_html.write("</html>\n")
res_html.close()
numtotal = len(threads)
thr_ok = [t for t in threads if t.lastcorrectstep == len(args.passes) - 1]
thr_ko = [t for t in threads if t.lastcorrectstep != len(args.passes) - 1]
print("{}/{} OK.".format(len(thr_ok), numtotal))
print("{}/{} KO : {}".format(
len(thr_ko), numtotal, list(map((lambda t: (t.filename, t.lastcorrectstep)), thr_ko))))
if args.verbose >= 1:
for thr in thr_ko + (thr_ok if args.verbose >= 2 else []):
print(thr.filename)
print("STDOUT: \n{}".format(thr.stdout))
print("STDERR: \n{}".format(thr.stderr))
if __name__ == "__main__":
main()
int main(int a){
if(a > 12){
a = 1;
} else { a = 3 * a; }
return a;
}
{"output": "", "error": null, "retval": 1}
\ No newline at end of file
{"output": "", "error": null, "retval": 3}
\ No newline at end of file
SYM_INT
SYM_IDENTIFIER(main)
SYM_LPARENTHESIS
SYM_INT
SYM_IDENTIFIER(a)
SYM_RPARENTHESIS
SYM_LBRACE
SYM_IF
SYM_LPARENTHESIS
SYM_IDENTIFIER(a)
SYM_GT
SYM_INTEGER(12)
SYM_RPARENTHESIS
SYM_LBRACE
SYM_IDENTIFIER(a)
SYM_ASSIGN
SYM_INTEGER(1)
SYM_SEMICOLON
SYM_RBRACE
SYM_ELSE
SYM_LBRACE
SYM_IDENTIFIER(a)
SYM_ASSIGN
SYM_INTEGER(3)
SYM_ASTERISK
SYM_IDENTIFIER(a)
SYM_SEMICOLON
SYM_RBRACE
SYM_RETURN
SYM_IDENTIFIER(a)
SYM_SEMICOLON
SYM_RBRACE
SYM_EOF
int main(int a){
int x;
if(a < 12){
if(a < 23){
x = 1;
} else {
x = 3;
}
} else {
if (a < 12){
x = 2;
} else {
x = 4;
}
}
return x;
}
{"output": "", "error": null, "retval": 4}
\ No newline at end of file
{"output": "", "error": null, "retval": 1}
\ No newline at end of file
SYM_INT
SYM_IDENTIFIER(main)
SYM_LPARENTHESIS
SYM_INT
SYM_IDENTIFIER(a)
SYM_RPARENTHESIS
SYM_LBRACE
SYM_INT
SYM_IDENTIFIER(x)
SYM_SEMICOLON
SYM_IF
SYM_LPARENTHESIS
SYM_IDENTIFIER(a)
SYM_LT
SYM_INTEGER(12)
SYM_RPARENTHESIS
SYM_LBRACE
SYM_IF
SYM_LPARENTHESIS
SYM_IDENTIFIER(a)
SYM_LT
SYM_INTEGER(23)
SYM_RPARENTHESIS
SYM_LBRACE
SYM_IDENTIFIER(x)
SYM_ASSIGN
SYM_INTEGER(1)
SYM_SEMICOLON
SYM_RBRACE
SYM_ELSE
SYM_LBRACE
SYM_IDENTIFIER(x)
SYM_ASSIGN
SYM_INTEGER(3)
SYM_SEMICOLON
SYM_RBRACE
SYM_RBRACE
SYM_ELSE
SYM_LBRACE
SYM_IF
SYM_LPARENTHESIS
SYM_IDENTIFIER(a)
SYM_LT
SYM_INTEGER(12)
SYM_RPARENTHESIS
SYM_LBRACE
SYM_IDENTIFIER(x)
SYM_ASSIGN
SYM_INTEGER(2)
SYM_SEMICOLON
SYM_RBRACE
SYM_ELSE
SYM_LBRACE
SYM_IDENTIFIER(x)
SYM_ASSIGN
SYM_INTEGER(4)
SYM_SEMICOLON
SYM_RBRACE
SYM_RBRACE
SYM_RETURN
SYM_IDENTIFIER(x)
SYM_SEMICOLON
SYM_RBRACE
SYM_EOF
int main(int x, int y){
return 2 * x + y;
}
{"output": "", "error": null, "retval": 40}
\ No newline at end of file
{"output": "", "error": null, "retval": 4}
\ No newline at end of file
SYM_INT
SYM_IDENTIFIER(main)
SYM_LPARENTHESIS
SYM_INT
SYM_IDENTIFIER(x)
SYM_COMMA
SYM_INT
SYM_IDENTIFIER(y)
SYM_RPARENTHESIS
SYM_LBRACE
SYM_RETURN
SYM_INTEGER(2)
SYM_ASTERISK
SYM_IDENTIFIER(x)
SYM_PLUS
SYM_IDENTIFIER(y)
SYM_SEMICOLON
SYM_RBRACE
SYM_EOF
int main(){
int a = 5 * 7;
if(a > 12){
a = 1;
} else { a = 3 * a; }
return a;
}
{"output": "", "error": null, "retval": 1}
\ No newline at end of file
{"output": "", "error": null, "retval": 1}
\ No newline at end of file
SYM_INT
SYM_IDENTIFIER(main)
SYM_LPARENTHESIS
SYM_RPARENTHESIS
SYM_LBRACE
SYM_INT
SYM_IDENTIFIER(a)
SYM_ASSIGN
SYM_INTEGER(5)
SYM_ASTERISK
SYM_INTEGER(7)
SYM_SEMICOLON
SYM_IF
SYM_LPARENTHESIS
SYM_IDENTIFIER(a)
SYM_GT
SYM_INTEGER(12)
SYM_RPARENTHESIS
SYM_LBRACE
SYM_IDENTIFIER(a)
SYM_ASSIGN
SYM_INTEGER(1)
SYM_SEMICOLON
SYM_RBRACE
SYM_ELSE
SYM_LBRACE
SYM_IDENTIFIER(a)
SYM_ASSIGN
SYM_INTEGER(3)
SYM_ASTERISK
SYM_IDENTIFIER(a)
SYM_SEMICOLON
SYM_RBRACE
SYM_RETURN
SYM_IDENTIFIER(a)
SYM_SEMICOLON
SYM_RBRACE
SYM_EOF
int main(){
int a = 3;
return (a*5)+4*(3-2);
}
{"output": "", "error": null, "retval": 19}
\ No newline at end of file