2025-01-21 23:46:40 +08:00
|
|
|
module Parsing
|
|
|
|
using ParserCombinator
|
2025-01-25 02:23:13 +08:00
|
|
|
using Match
|
|
|
|
|
|
|
|
include("passes.jl")
|
|
|
|
using .Passes
|
2025-01-21 23:46:40 +08:00
|
|
|
|
|
|
|
#=
|
|
|
|
grammar rules of uahgi
|
|
|
|
=#
|
|
|
|
|
2025-01-25 02:23:13 +08:00
|
|
|
comment = P"\%[^%]+\%"
|
|
|
|
newline = P"(\r?\n)" |> Passes.Classes.NL
|
|
|
|
space = p"[ \t]" > Passes.Classes.SPACE
|
2025-01-21 23:46:40 +08:00
|
|
|
|
2025-01-25 02:23:13 +08:00
|
|
|
id_name = p"[_a-zA-Z][_0-9a-zA-Z]*" > Passes.Classes.ID
|
2025-01-21 23:46:40 +08:00
|
|
|
id = E"@" + id_name
|
|
|
|
|
2025-01-25 02:23:13 +08:00
|
|
|
char = p"[^ \n\r\t\\]" |> Passes.Classes.CHAR #[1:2,:?]
|
2025-01-21 23:46:40 +08:00
|
|
|
|
|
|
|
# chars should be preceded by "\" are \, {, }, |, @, %
|
2025-01-25 02:23:13 +08:00
|
|
|
esc_char = p"[\{\|\}\@\%]" > Passes.Classes.ESC_CHAR
|
2025-01-21 23:46:40 +08:00
|
|
|
esc_combined = E"\\" + esc_char
|
|
|
|
#=
|
|
|
|
seq = (foo x1 x2 " ")
|
|
|
|
=> {@foo|x1|x2| }
|
|
|
|
=#
|
|
|
|
char_and_combined = char | esc_combined
|
2025-01-25 02:23:13 +08:00
|
|
|
seq_item = id | Repeat(char_and_combined) |> Passes.Classes.ELE
|
2025-01-21 23:46:40 +08:00
|
|
|
seq_item_rest = E"|" + seq_item
|
2025-01-25 02:23:13 +08:00
|
|
|
seq_inner = seq_item + (seq_item_rest)[0:end] |> Passes.Classes.SEQ
|
2025-01-21 23:46:40 +08:00
|
|
|
seq = E"{" + seq_inner + E"}"
|
|
|
|
|
|
|
|
|
|
|
|
part = seq | comment | space | newline | id | char
|
2025-01-25 02:23:13 +08:00
|
|
|
all = (Repeat(part) + Eos()) |> Passes.Classes.PROG
|
2025-01-21 23:46:40 +08:00
|
|
|
|
|
|
|
function parse(input)
|
|
|
|
print(input)
|
2025-01-25 02:23:13 +08:00
|
|
|
ast = parse_one(input, all)[1]
|
|
|
|
print("\n" * string(ast) * "\n")
|
|
|
|
|
2025-01-21 23:46:40 +08:00
|
|
|
|
|
|
|
#print(parse_one(, Pattern(r".b.")))
|
2025-01-25 02:23:13 +08:00
|
|
|
|
|
|
|
passes = Passes.processed_passes
|
|
|
|
|
|
|
|
|
|
|
|
ast_val = ast.val
|
|
|
|
for pass in passes
|
|
|
|
ast_val = use_pass(ast_val, pass)
|
|
|
|
end
|
|
|
|
|
|
|
|
new_ast = Passes.Classes.PROG(ast_val)
|
|
|
|
print(ast_to_string(new_ast))
|
|
|
|
return ast
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function ast_pattern_matched(pattern, ast_head)
|
|
|
|
zipped = zip(pattern, ast_head)
|
|
|
|
zipped_mapped = map(x -> match_unit(x), zipped)
|
|
|
|
is_all_matched = reduce((x,y)-> x && y, zipped_mapped)
|
|
|
|
return is_all_matched
|
|
|
|
end
|
|
|
|
|
|
|
|
function match_unit(pair)
|
|
|
|
pattern = pair[1]
|
|
|
|
ast_item = pair[2]
|
|
|
|
|
|
|
|
if typeof(pattern) == Passes.Classes.PTN_RGX
|
|
|
|
is_matched = match(pattern.val, ast_item.val)
|
|
|
|
return is_matched
|
|
|
|
else
|
|
|
|
return pattern.val == ast_item.val
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function use_pass(ast_val, pass)
|
|
|
|
pass_pattern = pass.pattern
|
|
|
|
pass_pattern_length = length(pass_pattern)
|
|
|
|
if length(ast_val) < pass_pattern_length
|
|
|
|
return ast_val
|
|
|
|
else
|
|
|
|
ast_head = ast_val[1:pass_pattern_length]
|
|
|
|
|
|
|
|
if ast_pattern_matched(pass_pattern, ast_head)
|
|
|
|
ast_head = pass.func(ast_head)
|
|
|
|
remained = use_pass([ast_head[2:end];ast_val[pass_pattern_length+1:end]], pass)
|
|
|
|
ast_val = [ast_head[1]; remained]
|
|
|
|
else
|
|
|
|
return ast_val
|
|
|
|
end
|
|
|
|
end
|
2025-01-21 23:46:40 +08:00
|
|
|
end
|
2025-01-25 02:23:13 +08:00
|
|
|
|
|
|
|
function ast_to_string(ast)
|
|
|
|
item = 5
|
|
|
|
str = @match ast begin
|
|
|
|
Passes.Classes.PROG(v) => begin
|
|
|
|
prog_inner = reduce( (x, y) -> x*" "*y, map(i -> ast_to_string(i), v))
|
|
|
|
return "[" * prog_inner * "]"
|
|
|
|
end
|
|
|
|
Passes.Classes.SEQ(v) => begin
|
|
|
|
prog_inner = reduce( (x, y) -> x*" "*y, map(i -> ast_to_string(i), v))
|
|
|
|
return "(" * prog_inner * ")"
|
|
|
|
end
|
|
|
|
Passes.Classes.ID(v) => "[ID: " * v * "]"
|
|
|
|
Passes.Classes.ELE(v) => begin
|
|
|
|
prog_inner = reduce( (x, y) -> x*" "*y, map(i -> ast_to_string(i), v))
|
|
|
|
return "[ELE : (" * prog_inner * ")]"
|
|
|
|
end
|
|
|
|
Passes.Classes.ESC_CHAR(ch) => "[ESC:\"" * ch[1] * "\"]"
|
|
|
|
Passes.Classes.CHAR(ch) => "\"" * ch[1] * "\""
|
|
|
|
Passes.Classes.NL(_) => "NL"
|
|
|
|
Passes.Classes.SPACE(_) => "SPACE"
|
|
|
|
|
|
|
|
|
|
|
|
_ => string(ast)
|
|
|
|
end
|
|
|
|
return str
|
|
|
|
end
|
|
|
|
|
2025-01-21 23:46:40 +08:00
|
|
|
# Write your package code here.
|
2025-01-25 02:23:13 +08:00
|
|
|
#export cat
|
2025-01-21 23:46:40 +08:00
|
|
|
|
2025-01-25 02:23:13 +08:00
|
|
|
#cat = 1.2
|
2025-01-21 23:46:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
end
|