Commit 86d15249 authored by Jamie A. Jennings's avatar Jamie A. Jennings

Started the refactoring, and cleaned up some small things

parent 40cd9ad0
......@@ -127,7 +127,9 @@ local function run(args)
-- load the file being tested
-- call the test procedure
cli_test = assert(rosie.import("unittest"), "failed to open unittest package")
cli_test.setup(en, rosie.attributes.ROSIE_LIBDIR)
-- FUTURE: handle versions like "1.2.3" ==> "rpl_1_2.rpl"
local rpl_definition_file = "rpl_" .. tostring(en.compiler.version):gsub("%.", "_")
cli_test.setup(en, "rosie/" .. rpl_definition_file)
local total_errors, total_failures, total_blocked = 0, 0, 0
local total_passed, total_tests = 0, 0
local total_files, total_compiled = 0, 0
......
......@@ -111,7 +111,7 @@ local function insert_seq_operators(exps)
if is_atmosphere(item) then
-- no op, just enqueue it into the result list
elseif item.type=="operator" then
assert( last_seen )
--!assert( last_seen )
last_seen = "OP"
-- enqueue it into the result list
else
......@@ -159,10 +159,8 @@ local function shunting_yard_exp(exp, attribute_table)
e=exp.e,
data=exp.data,
subs=map_shunting_yard_exp(exp.subs)}
elseif exp.type == "form.grammar_exp" then
assert(false, "unhandled expression type")
elseif exp.type == "form.let_exp" then
assert(false, "unhandled expression type")
elseif exp.type == "form.grammar_exp" or exp.type == "form.let_exp" then
error("unhandled expression type: " .. exp.type)
elseif exp.type == "form.application" then
local n = #exp.subs
local arg_form = exp.subs[n]
......@@ -219,15 +217,15 @@ local OPERATOR_ATTRIBUTES =
local function should_push(op, stack_top, attribute_table)
local attr = attribute_table[op]
assert(attr, "unknown operator: " .. tostring(op))
if not stack_top then
-- stack is empty
return true
else
local stack_op_attr = attribute_table[stack_top.data]
assert(attr, "unknown operator: " .. tostring(stack_top.data))
if (attr.precedence > stack_op_attr.precedence) or
( (attr.precedence == stack_op_attr.precedence) and
local op_precedence = attr.precedence
local stack_op_precedence = stack_op_attr.precedence
if (op_precedence > stack_op_precedence) or
( (op_precedence == stack_op_precedence) and
(attr.associativity == "right") ) then
return true
else
......@@ -236,7 +234,7 @@ local function should_push(op, stack_top, attribute_table)
return false
end
end
assert(false, "should not get here")
error("should not get here")
end
-- The stack of expressions in the original shunting yard algorithm contains
......@@ -268,12 +266,11 @@ local function make_prefix_tree(op, exps)
show("right operand: ", right)
show("left operand: ", left)
end
assert(right[1], "missing right operand for: " .. op.data)
assert(left[1], "missing left operand for: " .. op.data)
--!assert(right[1], "missing right operand for: " .. op.data)
--!assert(left[1], "missing left operand for: " .. op.data)
op.subs = list.append(left, right)
-- Convert generic "operator" nodes to choice, sequence, or and_exp
local attr = OPERATOR_ATTRIBUTES[op.data]
assert(attr)
op.type = attr.nodetype
if infix.DEBUG then
print("result: ", op.type); --table.print(op)
......@@ -313,8 +310,9 @@ function shunting_yard_explist(subs, attribute_table)
exps.push(e)
elseif e.type == "operator" then
while not should_push(e.data, opstack.peek(), attribute_table) do
-- To produce a postfix sequence of exps and ops:
-- exps.push(opstack.pop())
-- To produce a postfix sequence of exps and ops, as original
-- shunting yard algorithm did:
-- exps.push(opstack.pop())
-- Instead, we will convert to prefix in tree form. Would be
-- simpler except that there's atmosphere on the exps stack.
exps.push(make_prefix_tree(opstack.pop(), exps))
......@@ -359,7 +357,7 @@ local function handle_statement(s)
elseif s.type=="form.simple" then
local newsubs = {}
local n = #s.subs
assert( s.subs[n].type=="form.exp" )
--!assert( s.subs[n].type=="form.exp" )
for i=1,n-1 do newsubs[i] = s.subs[i] end
newsubs[n] = shunting_yard(s.subs[n])
return {type=s.type,
......@@ -368,7 +366,7 @@ local function handle_statement(s)
data=s.data,
subs = newsubs}
elseif s.type=="form.grammar_block" then
assert(s.subs[1].type=="form.bindings")
--!assert(s.subs[1].type=="form.bindings")
-- there may be one set of bindings or two
local newsubs = {}
for _, bindings in ipairs(s.subs) do
......@@ -405,14 +403,14 @@ end
function infix.to_prefix(pt)
if pt.type=="rpl_expression" then
assert(pt.subs)
--!assert(pt.subs)
return {type = pt.type,
s = pt.s,
e = pt.e,
data = pt.data,
subs = map(shunting_yard, pt.subs)}
elseif pt.type=="rpl_statements" then
assert(pt.subs)
--!assert(pt.subs)
return {type = pt.type,
s = pt.s,
e = pt.e,
......
......@@ -37,20 +37,22 @@ local function find_test_lines(str)
end
-- setup the engine that will parse the test lines in the rpl file
function unittest.setup(en, libdir)
function unittest.setup(en, rpl_definition_file)
local test_patterns =
[==[
includesKeyword = ("includes" / "excludes")
includesClause = includesKeyword rpl_1_2.identifier
identifier = rpl.identifier -- rename
quoted_string = rpl.quoted_string
includesKeyword = "includes" / "excludes"
includesClause = includesKeyword identifier
testKeyword = "accepts" / "rejects"
test_local = "local"
test_line = ("--test"/"-- test")
test_line = ("--test" / "-- test")
test_local?
rpl_1_2.identifier
identifier
(testKeyword / includesClause)
(rpl_1_2.quoted_string ("," rpl_1_2.quoted_string)*)?
]==]
local ok, errs = en:loadfile(libdir .. "/rosie/rpl_1_2.rpl")
(quoted_string ("," quoted_string)*)?
]==]
local ok, pkgname, errs = en:import(rpl_definition_file, "rpl")
if not ok then
for _,v in ipairs(errs or {}) do
write_error(violation.tostring(v))
......@@ -80,6 +82,17 @@ function unittest.write_test_result(...)
io.write("\n")
end
local function extract_test_string(p)
assert(p.type == "quoted_string")
assert(p.subs and p.subs[1].type == "rpl.literal")
local data = p.subs[1].data
local teststr, esc_err = ustring.unescape_string(data)
if not teststr then
return false, esc_err or "test input is not a valid Rosie string", "error"
end
return teststr
end
-- Args:
-- rosie, the rosie module (for creating a new engine, and rplx objects for en)
-- en, the engine that has patterns for extracting test cases
......@@ -240,12 +253,9 @@ function unittest.run(rosie, en, args, filename)
local containedIdentifier = t.subs[2].data
for i = literals, #m.subs do
total = total + 1
local includes, teststr, esc_err, msg
teststr, esc_err = ustring.unescape_string(m.subs[i].data)
if not teststr then
msg = esc_err or "test input is not a valid Rosie string"
includes = "error"
else
local includes, teststr, msg
teststr, msg = extract_test_string(m.subs[i])
if teststr then
includes = test_includes_ident(testIdentifier,
teststr,
containedIdentifier,
......@@ -267,7 +277,12 @@ function unittest.run(rosie, en, args, filename)
else
msg = nil
end
end -- if teststr is a valid Rosie string
else
-- not a valid test string
-- 'msg' already set by extract_test_string()
includes = "error"
end -- if we have a valid test string
if msg then
if includes==nil then
blocked = blocked + 1
......@@ -288,11 +303,10 @@ function unittest.run(rosie, en, args, filename)
local should_accept = (m.subs[2].data == "accepts")
for i = literals, #m.subs do
total = total + 1
local teststr, esc_err
teststr, esc_err = ustring.unescape_string(m.subs[i].data) -- allow, e.g. \" inside the test string
local teststr, msg = extract_test_string(m.subs[i])
if not teststr then
errors = errors + 1
unittest.write_test_result("ERROR: ", esc_err)
unittest.write_test_result("ERROR: ", msg)
else
local result = test_exp(testIdentifier, teststr, should_accept, is_local_identifier)
if not result then
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment