parser.mly 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. %{
  2. module T = Qsp_syntax.T
  3. open StdLabels
  4. type action_block =
  5. { loc : Qsp_syntax.S.pos
  6. ; expression :
  7. Analyzer.Expression.t'
  8. ; body : Analyzer.Instruction.t list
  9. ; pos : Qsp_syntax.S.pos
  10. ; clauses : (
  11. ( (Analyzer.Instruction.expression, Analyzer.Instruction.t) Qsp_syntax.S.clause list
  12. * (Qsp_syntax.S.pos * Analyzer.Instruction.t list) option
  13. ) option )
  14. }
  15. module Helper = Qsp_syntax.S.Helper(Analyzer.Expression)
  16. %}
  17. %parameter<Analyzer: Qsp_syntax.S.Analyzer>
  18. %start <(Analyzer.Location.t)>main
  19. %on_error_reduce expression instruction unary_operator assignation_operator
  20. %%
  21. main:
  22. | before_location*
  23. LOCATION_START
  24. EOL+
  25. instructions = line_statement*
  26. LOCATION_END
  27. {
  28. let instructions = List.map instructions ~f:(Analyzer.Instruction.v) in
  29. Analyzer.Location.location $loc instructions
  30. }
  31. before_location:
  32. | EOL {}
  33. | COMMENT EOL { }
  34. (* All these statement should terminate with EOL *)
  35. line_statement:
  36. | COMMENT EOL+ { Analyzer.Instruction.comment $loc }
  37. | COLUMN i=IDENT EOL* { Analyzer.Instruction.location $loc i }
  38. | s = terminated(instruction, line_sep)
  39. | s = terminated(inline_action, line_sep)
  40. { s }
  41. | a = action_bloc(IF, elif_else_body)
  42. { let {loc; expression; body; pos; clauses } = a in
  43. let elifs, else_ = match clauses with
  44. | None -> [], None
  45. | Some (elifs, else_) -> (elifs, else_)
  46. in
  47. Analyzer.Instruction.if_
  48. loc
  49. (pos, expression, body)
  50. ~elifs
  51. ~else_
  52. }
  53. | a = action_bloc(ACT, empty_body)
  54. { let {loc; expression; body; _} = a in
  55. Analyzer.Instruction.act loc ~label:expression body
  56. }
  57. (** Represent an instruction which can either be on a single line,
  58. or created in a block until an END
  59. *)
  60. %inline action_bloc(TOKEN, BODY):
  61. | TOKEN
  62. e = expression
  63. COLUMN EOL+
  64. s = line_statement*
  65. b = BODY
  66. END TOKEN?
  67. line_sep
  68. {
  69. let expression = Analyzer.Expression.v e in
  70. let clauses = match b with
  71. | None -> None
  72. | Some (elifs, clauses) ->
  73. let elifs = begin match elifs with
  74. | [] -> []
  75. | _ ->
  76. List.map elifs
  77. ~f:(fun ((pos:Qsp_syntax.S.pos), e, instructions) ->
  78. let e = Analyzer.Expression.v e in
  79. (pos, e, instructions)
  80. )
  81. end in
  82. Some (elifs, clauses)
  83. in
  84. { loc = $loc
  85. ; expression
  86. ; body = s
  87. ; clauses
  88. ; pos = $loc(s)
  89. }
  90. }
  91. empty_body:
  92. | { None }
  93. elif:
  94. | ELIF
  95. e = expression
  96. COLUMN EOL+
  97. s = line_statement*
  98. { $loc, e, s }
  99. else_:
  100. | ELSE EOL+
  101. expressions = line_statement*
  102. { Some ($loc, expressions) }
  103. | { None }
  104. elif_else_body:
  105. | elifs = elif*
  106. else_ = else_
  107. { Some (elifs, else_) }
  108. %inline line_sep:
  109. | EOL+
  110. | AMPERSAND+ EOL*
  111. {}