add basic macro expansion
This commit is contained in:
parent
f010267f11
commit
38a752be5a
6 changed files with 150 additions and 25 deletions
|
@ -5,6 +5,7 @@ version = "1.0.0-DEV"
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63"
|
ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63"
|
||||||
|
Match = "7eb4fadd-790c-5f42-8a69-bfa0b872bfbf"
|
||||||
ParserCombinator = "fae87a5f-d1ad-5cf0-8f61-c941e1580b46"
|
ParserCombinator = "fae87a5f-d1ad-5cf0-8f61-c941e1580b46"
|
||||||
libharu_jll = "d4e8948d-4b7e-5538-9d15-404f6f0a9070"
|
libharu_jll = "d4e8948d-4b7e-5538-9d15-404f6f0a9070"
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
@foo
|
|
||||||
{@foo|@bar|12\|}
|
|
||||||
|
|
13
src/classes.jl
Normal file
13
src/classes.jl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
module Classes
|
||||||
|
abstract type Node end
|
||||||
|
struct ID<:Node val end
|
||||||
|
struct SEQ<:Node val end # like (a b c) in scheme
|
||||||
|
struct ELE<:Node val end #an element in a seq
|
||||||
|
struct ESC_CHAR<:Node val end # character preceded by escape char "\"
|
||||||
|
struct CHAR<:Node val end #character
|
||||||
|
struct SPACE<:Node val end # space
|
||||||
|
struct NL<:Node val end # newline
|
||||||
|
struct PROG<:Node val end # all the program
|
||||||
|
# pattern in regex form
|
||||||
|
struct PTN_RGX<:Node val::Regex end
|
||||||
|
end
|
114
src/parsing.jl
114
src/parsing.jl
|
@ -1,52 +1,130 @@
|
||||||
module Parsing
|
module Parsing
|
||||||
using ParserCombinator
|
using ParserCombinator
|
||||||
abstract type Node end
|
using Match
|
||||||
struct ID<:Node val end
|
|
||||||
struct SEQ<:Node val end # like (a b c) in scheme
|
include("passes.jl")
|
||||||
struct ELE<:Node val end #an element in a seq
|
using .Passes
|
||||||
struct ESC_CHAR<:Node val end # character preceded by escape char "\"
|
|
||||||
|
|
||||||
#=
|
#=
|
||||||
grammar rules of uahgi
|
grammar rules of uahgi
|
||||||
=#
|
=#
|
||||||
|
|
||||||
comment = p"\%[^%]+\%"
|
comment = P"\%[^%]+\%"
|
||||||
newline = p"(\r?\n)"
|
newline = P"(\r?\n)" |> Passes.Classes.NL
|
||||||
space = p"[ \t]"
|
space = p"[ \t]" > Passes.Classes.SPACE
|
||||||
|
|
||||||
id_name = p"[_a-zA-Z][_0-9a-zA-Z]*" > ID
|
id_name = p"[_a-zA-Z][_0-9a-zA-Z]*" > Passes.Classes.ID
|
||||||
id = E"@" + id_name
|
id = E"@" + id_name
|
||||||
|
|
||||||
char = p"[^ \n\r\t\\]"#[1:2,:?]
|
char = p"[^ \n\r\t\\]" |> Passes.Classes.CHAR #[1:2,:?]
|
||||||
|
|
||||||
# chars should be preceded by "\" are \, {, }, |, @, %
|
# chars should be preceded by "\" are \, {, }, |, @, %
|
||||||
esc_char = p"[\{\|\}\@\%]" > ESC_CHAR
|
esc_char = p"[\{\|\}\@\%]" > Passes.Classes.ESC_CHAR
|
||||||
esc_combined = E"\\" + esc_char
|
esc_combined = E"\\" + esc_char
|
||||||
#=
|
#=
|
||||||
seq = (foo x1 x2 " ")
|
seq = (foo x1 x2 " ")
|
||||||
=> {@foo|x1|x2| }
|
=> {@foo|x1|x2| }
|
||||||
=#
|
=#
|
||||||
char_and_combined = char | esc_combined
|
char_and_combined = char | esc_combined
|
||||||
seq_item = id | Repeat(char_and_combined) |> ELE
|
seq_item = id | Repeat(char_and_combined) |> Passes.Classes.ELE
|
||||||
seq_item_rest = E"|" + seq_item
|
seq_item_rest = E"|" + seq_item
|
||||||
seq_inner = seq_item + (seq_item_rest)[0:end] |> SEQ
|
seq_inner = seq_item + (seq_item_rest)[0:end] |> Passes.Classes.SEQ
|
||||||
seq = E"{" + seq_inner + E"}"
|
seq = E"{" + seq_inner + E"}"
|
||||||
|
|
||||||
|
|
||||||
part = seq | comment | space | newline | id | char
|
part = seq | comment | space | newline | id | char
|
||||||
all = Repeat(part) + Eos()
|
all = (Repeat(part) + Eos()) |> Passes.Classes.PROG
|
||||||
|
|
||||||
function parse(input)
|
function parse(input)
|
||||||
print(input)
|
print(input)
|
||||||
b = parse_one(input, all)
|
ast = parse_one(input, all)[1]
|
||||||
print("\n" * string(b) * "\n")
|
print("\n" * string(ast) * "\n")
|
||||||
|
|
||||||
|
|
||||||
#print(parse_one(, Pattern(r".b.")))
|
#print(parse_one(, Pattern(r".b.")))
|
||||||
|
|
||||||
|
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
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
# Write your package code here.
|
# Write your package code here.
|
||||||
#export dog
|
#export cat
|
||||||
|
|
||||||
#dog = 1.2
|
#cat = 1.2
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
29
src/passes.jl
Normal file
29
src/passes.jl
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
module Passes
|
||||||
|
include("classes.jl")
|
||||||
|
using .Classes
|
||||||
|
|
||||||
|
export processed_passes, Pass
|
||||||
|
processed_passes = []
|
||||||
|
|
||||||
|
struct Pass
|
||||||
|
pattern
|
||||||
|
func
|
||||||
|
end
|
||||||
|
|
||||||
|
####definition of passes ####
|
||||||
|
|
||||||
|
# 2 newline become @par{}
|
||||||
|
function two_nl_to_par_pass_func(two_nl)
|
||||||
|
return [Classes.SEQ([Classes.ID("par")])]
|
||||||
|
end
|
||||||
|
two_nl_to_par_pattern = [Classes.NL([]), Classes.NL([])] #two continuous newline
|
||||||
|
|
||||||
|
|
||||||
|
two_nl_to_par_pass = Pass(two_nl_to_par_pattern,
|
||||||
|
two_nl_to_par_pass_func)
|
||||||
|
|
||||||
|
|
||||||
|
push!(processed_passes, two_nl_to_par_pass)
|
||||||
|
|
||||||
|
end
|
10
src/uahgi.jl
10
src/uahgi.jl
|
@ -1,5 +1,5 @@
|
||||||
module uahgi
|
module uahgi
|
||||||
include("./parsing.jl")
|
include("parsing.jl")
|
||||||
using .Parsing
|
using .Parsing
|
||||||
using ArgParse
|
using ArgParse
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ function parse_commandline()
|
||||||
@add_arg_table! s begin
|
@add_arg_table! s begin
|
||||||
"FILE"
|
"FILE"
|
||||||
help = "the file path to be converted."
|
help = "the file path to be converted."
|
||||||
required = true
|
#required = true
|
||||||
end
|
end
|
||||||
|
|
||||||
return parse_args(s)
|
return parse_args(s)
|
||||||
|
@ -21,7 +21,11 @@ end
|
||||||
|
|
||||||
function main()
|
function main()
|
||||||
parsed_args = parse_commandline()
|
parsed_args = parse_commandline()
|
||||||
file_path = parsed_args["FILE"]
|
if parsed_args["FILE"] === nothing
|
||||||
|
file_path = "./example/ex1.ug" # for test
|
||||||
|
else
|
||||||
|
file_path = parsed_args["FILE"]
|
||||||
|
end
|
||||||
file_content = open(f->read(f, String), file_path)
|
file_content = open(f->read(f, String), file_path)
|
||||||
Parsing.parse(file_content)
|
Parsing.parse(file_content)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue