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] | ||||
| ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63" | ||||
| Match = "7eb4fadd-790c-5f42-8a69-bfa0b872bfbf" | ||||
| ParserCombinator = "fae87a5f-d1ad-5cf0-8f61-c941e1580b46" | ||||
| 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 | ||||
							
								
								
									
										118
									
								
								src/parsing.jl
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								src/parsing.jl
									
									
									
									
									
								
							|  | @ -1,52 +1,130 @@ | |||
| module Parsing | ||||
| using ParserCombinator | ||||
| 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 "\" | ||||
| using Match | ||||
| 
 | ||||
| include("passes.jl") | ||||
| using .Passes | ||||
| 
 | ||||
| #= | ||||
| grammar rules of uahgi | ||||
| =# | ||||
| 
 | ||||
| comment = p"\%[^%]+\%" | ||||
| newline = p"(\r?\n)" | ||||
| space = p"[ \t]" | ||||
| comment = P"\%[^%]+\%" | ||||
| newline = P"(\r?\n)" |> Passes.Classes.NL | ||||
| 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 | ||||
| 
 | ||||
| char = p"[^ \n\r\t\\]"#[1:2,:?] | ||||
| char = p"[^ \n\r\t\\]" |> Passes.Classes.CHAR #[1:2,:?] | ||||
| 
 | ||||
| # chars should be preceded by "\" are \, {, }, |, @, % | ||||
| esc_char = p"[\{\|\}\@\%]" > ESC_CHAR | ||||
| esc_char = p"[\{\|\}\@\%]" > Passes.Classes.ESC_CHAR | ||||
| esc_combined = E"\\" + esc_char | ||||
| #= | ||||
| seq = (foo x1 x2 " ") | ||||
| => {@foo|x1|x2| } | ||||
| =# | ||||
| 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_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"}" | ||||
| 
 | ||||
| 
 | ||||
| part =  seq | comment | space | newline | id | char | ||||
| all = Repeat(part) + Eos() | ||||
| all = (Repeat(part) + Eos()) |> Passes.Classes.PROG | ||||
| 
 | ||||
| function parse(input) | ||||
|     print(input) | ||||
|     b = parse_one(input, all) | ||||
|     print("\n" * string(b) * "\n") | ||||
|     ast = parse_one(input, all)[1] | ||||
|     print("\n" * string(ast) * "\n") | ||||
|      | ||||
|      | ||||
|     #print(parse_one(, Pattern(r".b."))) | ||||
| end | ||||
| # Write your package code here. | ||||
| #export dog | ||||
|      | ||||
|     passes = Passes.processed_passes | ||||
| 
 | ||||
| #dog = 1.2 | ||||
| 
 | ||||
|     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 | ||||
| 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. | ||||
| #export cat | ||||
| 
 | ||||
| #cat = 1.2 | ||||
| 
 | ||||
| 
 | ||||
| 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 | ||||
| include("./parsing.jl") | ||||
| include("parsing.jl") | ||||
| using .Parsing | ||||
| using ArgParse | ||||
| 
 | ||||
|  | @ -12,7 +12,7 @@ function parse_commandline() | |||
|     @add_arg_table! s begin | ||||
|         "FILE" | ||||
|             help = "the file path to be converted." | ||||
|             required = true | ||||
|             #required = true | ||||
|     end | ||||
| 
 | ||||
|     return parse_args(s) | ||||
|  | @ -21,7 +21,11 @@ end | |||
| 
 | ||||
| function main() | ||||
|     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) | ||||
|     Parsing.parse(file_content) | ||||
| end | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue