Compiler/AST interpreter: Difference between revisions

Undo revision 275911 by Wherrera (talk)
(Undo revision 275911 by Wherrera (talk))
Line 1,366:
</lang>
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) = (i != 0)
 
function call2(op, x, y)
if op in ["And", "Or"]
x, y = tobool(x), tobool(y)
end
eval(Meta.parse("$(x) $(OP2[op]) $(y)"))
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))) ? eval(interp(x.right.left)) : eval(interp(x.right.right)); return nothing
elseif x.node_type == "While" while tobool(eval(interp(x.left))) eval(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)
if typeof(s) == String
print((i = tryparse(Int, s)) == nothing ? eval(Symbol(s)) : i)
else
eval(Meta.parse(show(s)))
end
return nothing
elseif x.node_type == "Prts" print(eval(interp(x.left))); return nothing
elseif x.node_type == "Sequence" eval(interp(x.left)); eval(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))
println("\n names: ", names(Main))
</lang>{{output}}<pre>
3 is prime
5 is prime
7 is prime
9 is prime
11 is prime
13 is prime
15 is prime
17 is prime
19 is prime
21 is prime
23 is prime
25 is prime
27 is prime
29 is prime
31 is prime
33 is prime
35 is prime
37 is prime
39 is prime
41 is prime
43 is prime
45 is prime
47 is prime
49 is prime
51 is prime
53 is prime
55 is prime
57 is prime
59 is prime
61 is prime
63 is prime
65 is prime
67 is prime
69 is prime
71 is prime
73 is prime
75 is prime
77 is prime
79 is prime
81 is prime
83 is prime
85 is prime
87 is prime
89 is prime
91 is prime
93 is prime
95 is prime
97 is prime
99 is prime
101 is prime
Total primes found: 51
</pre>
 
=={{header|Perl}}==
4,102

edits