aboutsummaryrefslogtreecommitdiff
path: root/lib/parser.mly
diff options
context:
space:
mode:
Diffstat (limited to 'lib/parser.mly')
-rw-r--r--lib/parser.mly91
1 files changed, 91 insertions, 0 deletions
diff --git a/lib/parser.mly b/lib/parser.mly
new file mode 100644
index 0000000..c506e9c
--- /dev/null
+++ b/lib/parser.mly
@@ -0,0 +1,91 @@
+
+%{
+
+
+ module T = Qsp_syntax.T
+
+ let dummy_pos = (Lexing.dummy_pos, Lexing.dummy_pos)
+
+%}
+
+%parameter<Analyzer: Qsp_syntax.S.Analyzer>
+%start <Analyzer.Location.repr>main
+
+%%
+
+main:
+ | EOL*
+ LOCATION_START
+ EOL+
+ expressions = line_statement*
+ LOCATION_END
+ EOL*
+ EOF
+ {
+ Analyzer.Location.location $loc expressions
+ }
+
+(* All these statement should terminate with EOL *)
+line_statement:
+ | COMMENT EOL+ { Analyzer.Instruction.comment $loc }
+ | COLUMN i=IDENT EOL* { Analyzer.Instruction.location $loc i }
+ | s = terminated(instruction, line_sep)
+ | s = terminated(inline_action, line_sep)
+ { s }
+ | a = action_bloc(IF, elif_else_body)
+ { let loc, expression, statements, loc_s, body = a in
+ let elifs, else_ = match body with
+ | None -> [], []
+ | Some (elifs, else_) -> (elifs, else_)
+ in
+ Analyzer.Instruction.if_
+ loc
+ (loc_s, expression, statements)
+ ~elifs
+ ~else_
+ }
+ | a = action_bloc(ACT, empty_body)
+ { let loc, label, statements, _, _ = a in
+ Analyzer.Instruction.act loc ~label statements
+ }
+
+(** Represent an instruction which can either be on a single line,
+ or created in a block until an END
+ *)
+%inline action_bloc(TOKEN, BODY):
+ | TOKEN
+ e = expression
+ COLUMN EOL+
+ s = line_statement*
+ b = BODY
+ END TOKEN?
+ line_sep
+ { $loc, e, s, $loc(s), b }
+
+empty_body:
+ | { None }
+
+elif:
+ | ELIF
+ e = expression
+ COLUMN EOL+
+ s = line_statement*
+ { $loc, e, s }
+
+else_:
+ | ELSE EOL+
+ expressions = line_statement*
+ { expressions }
+ | { [] }
+
+
+elif_else_body:
+ | elifs = elif*
+ else_ = else_
+ { Some (elifs, else_) }
+
+
+%inline line_sep:
+ | EOL+
+ | AMPERSAND+ EOL*
+ {}