aboutsummaryrefslogtreecommitdiff
path: root/lib/qparser/parser.mly
diff options
context:
space:
mode:
Diffstat (limited to 'lib/qparser/parser.mly')
-rw-r--r--lib/qparser/parser.mly89
1 files changed, 89 insertions, 0 deletions
diff --git a/lib/qparser/parser.mly b/lib/qparser/parser.mly
new file mode 100644
index 0000000..84c1af8
--- /dev/null
+++ b/lib/qparser/parser.mly
@@ -0,0 +1,89 @@
+
+%{
+ module T = Qsp_syntax.T
+%}
+
+%parameter<Analyzer: Qsp_syntax.S.Analyzer>
+%start <Analyzer.Location.repr>main
+%on_error_reduce expression instruction unary_operator assignation_operator
+
+%%
+
+main:
+ | before_location*
+ LOCATION_START
+ EOL+
+ expressions = line_statement*
+ LOCATION_END
+ {
+ Analyzer.Location.location $loc expressions
+ }
+
+before_location:
+ | EOL {}
+ | COMMENT EOL { }
+
+(* 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*
+ {}