Compiler/AST interpreter: Difference between revisions
Content added Content deleted
Line 1,366: | Line 1,366: | ||
</lang> |
</lang> |
||
Passes all tests. |
Passes all tests. |
||
=={{header|Julia}}== |
|||
<lang julia>struct Anode |
|||
node_type::String |
|||
left::Union{Nothing, Anode} |
|||
right::Union{Nothing, Anode} |
|||
value::Union{Nothing, String} |
|||
end |
|||
make_leaf(t, v) = Anode(t, nothing, nothing, v) |
|||
make_node(t, l, r) = Anode(t, l, r, nothing) |
|||
const OP2 = Dict("Multiply" => "*", "Divide" => "/", "Mod" => "%", "Add" => "+", "Subtract" => "-", |
|||
"Less" => "<", "Greater" => ">", "LessEqual" => "<=", "GreaterEqual" => ">=", |
|||
"Equal" => "==", "NotEqual" => "!=", "And" => "&&", "Or" => "||") |
|||
const OP1 = Dict("Not" => "!", "Minus" => "-") |
|||
tobool(i::Bool) = i |
|||
tobool(i::Int) = (i != 0) |
|||
tobool(s::String) = eval(Symbol(s)) != 0 |
|||
const stac = Vector{Any}() |
|||
function call2(op, x, y) |
|||
if op in ["And", "Or"] |
|||
x, y = tobool(x), tobool(y) |
|||
end |
|||
eval(Meta.parse("push!(stac, $(x) $(OP2[op]) $(y))")) |
|||
return Int(floor(pop!(stac))) |
|||
end |
|||
call1(op, x) = (if op in ["Not"] x = tobool(x) end; eval(Meta.parse("$(OP1[op]) $(x)"))) |
|||
evalpn(op, x, y = nothing) = (haskey(OP2, op) ? call2(op, x, y) : call1(op, x)) |
|||
function load_ast(io) |
|||
line = strip(readline(io)) |
|||
line_list = filter(x -> x != nothing, match(r"(?:(\w+)\s+(\d+|\w+|\".*\")|(\w+|;))", line).captures) |
|||
text = line_list[1] |
|||
if text == ";" |
|||
return nothing |
|||
end |
|||
node_type = text |
|||
if length(line_list) > 1 |
|||
return make_leaf(line_list[1], line_list[2]) |
|||
end |
|||
left = load_ast(io) |
|||
right = load_ast(io) |
|||
return make_node(line_list[1], left, right) |
|||
end |
|||
function interp(x) |
|||
if x == nothing return nothing |
|||
elseif x.node_type == "Integer" return parse(Int, x.value) |
|||
elseif x.node_type == "Identifier" return "_" * x.value |
|||
elseif x.node_type == "String" return replace(replace(x.value, "\"" => ""), "\\n" => "\n") |
|||
elseif x.node_type == "Assign" s = "$(interp(x.left)) = $(interp(x.right))"; eval(Meta.parse(s)); return nothing |
|||
elseif x.node_type in keys(OP2) return evalpn(x.node_type, interp(x.left), interp(x.right)) |
|||
elseif x.node_type in keys(OP1) return evalpn(x.node_type, interp(x.left)) |
|||
elseif x.node_type == "If" tobool(eval(interp(x.left))) ? interp(x.right.left) : interp(x.right.right); return nothing |
|||
elseif x.node_type == "While" while tobool(eval(interp(x.left))) interp(x.right) end; return nothing |
|||
elseif x.node_type == "Prtc" print(Char(eval(interp(x.left)))); return nothing |
|||
elseif x.node_type == "Prti" s = interp(x.left); print((i = tryparse(Int, s)) == nothing ? eval(Symbol(s)) : i); return nothing |
|||
elseif x.node_type == "Prts" print(eval(interp(x.left))); return nothing |
|||
elseif x.node_type == "Sequence" interp(x.left); interp(x.right); return nothing |
|||
else |
|||
throw("unknown node type: $x") |
|||
end |
|||
end |
|||
const testparsed = """ |
|||
Sequence |
|||
Sequence |
|||
Sequence |
|||
Sequence |
|||
Sequence |
|||
; |
|||
Assign |
|||
Identifier count |
|||
Integer 1 |
|||
Assign |
|||
Identifier n |
|||
Integer 1 |
|||
Assign |
|||
Identifier limit |
|||
Integer 100 |
|||
While |
|||
Less |
|||
Identifier n |
|||
Identifier limit |
|||
Sequence |
|||
Sequence |
|||
Sequence |
|||
Sequence |
|||
Sequence |
|||
; |
|||
Assign |
|||
Identifier k |
|||
Integer 3 |
|||
Assign |
|||
Identifier p |
|||
Integer 1 |
|||
Assign |
|||
Identifier n |
|||
Add |
|||
Identifier n |
|||
Integer 2 |
|||
While |
|||
And |
|||
LessEqual |
|||
Multiply |
|||
Identifier k |
|||
Identifier k |
|||
Identifier n |
|||
Identifier p |
|||
Sequence |
|||
Sequence |
|||
; |
|||
Assign |
|||
Identifier p |
|||
NotEqual |
|||
Multiply |
|||
Divide |
|||
Identifier n |
|||
Identifier k |
|||
Identifier k |
|||
Identifier n |
|||
Assign |
|||
Identifier k |
|||
Add |
|||
Identifier k |
|||
Integer 2 |
|||
If |
|||
Identifier p |
|||
If |
|||
Sequence |
|||
Sequence |
|||
; |
|||
Sequence |
|||
Sequence |
|||
; |
|||
Prti |
|||
Identifier n |
|||
; |
|||
Prts |
|||
String \" is prime\\n\" |
|||
; |
|||
Assign |
|||
Identifier count |
|||
Add |
|||
Identifier count |
|||
Integer 1 |
|||
; |
|||
Sequence |
|||
Sequence |
|||
Sequence |
|||
; |
|||
Prts |
|||
String \"Total primes found: \" |
|||
; |
|||
Prti |
|||
Identifier count |
|||
; |
|||
Prts |
|||
String \"\\n\" |
|||
; """ |
|||
const lio = IOBuffer(testparsed) |
|||
interp(load_ast(lio)) |
|||
</lang>{{output}}<pre> |
|||
3 is prime |
|||
5 is prime |
|||
7 is prime |
|||
11 is prime |
|||
13 is prime |
|||
17 is prime |
|||
19 is prime |
|||
23 is prime |
|||
29 is prime |
|||
31 is prime |
|||
37 is prime |
|||
41 is prime |
|||
43 is prime |
|||
47 is prime |
|||
53 is prime |
|||
59 is prime |
|||
61 is prime |
|||
67 is prime |
|||
71 is prime |
|||
73 is prime |
|||
79 is prime |
|||
83 is prime |
|||
89 is prime |
|||
97 is prime |
|||
101 is prime |
|||
Total primes found: 26 |
|||
</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |