1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
(**
This module describe the type an analyzer must implement in order to be
used with the parser.
The module is divided in three modules :
- Expression : the finest part of the QSP syntax.
- Instruction : if/act block,
- Location
All the elements of the syntax are represented with a dedicated function
(instead of a big sum type). The module [Tree] provide an implementation
which build the AST.
*)
type 'a repr = Report.t list -> 'a
type pos = Lexing.position * Lexing.position
(** Starting and ending position for the given location *)
type ('a, 'b) variable = { pos : 'a; name : string; index : 'b option }
(** Describe a variable, using the name in capitalized text, and an optionnal
index.
If missing, the index should be considered as [0].*)
type ('a, 'b) clause = pos * 'a * 'b repr list
(** Represent the evaluation over an expression *)
module type Expression = sig
type t
(** Internal type used in the evaluation *)
type t'
(** External type used outside of the module *)
val v : t -> t' * Report.t list
val ident : (pos, t) variable -> t
(*
Basic values, text, number…
*)
val integer : pos -> string -> t
val literal : pos -> string -> t
val function_ : pos -> T.function_ -> t list -> t
(** Call a function. The functions list is hardcoded in lib/lexer.mll *)
val uoperator : pos -> T.uoperator -> t -> t
(** Unary operator like [-123] or [+'Text']*)
val boperator : pos -> T.boperator -> t -> t -> t
(** Binary operator, for a comparaison, or an operation *)
end
module type Instruction = sig
type t
(** Internal type used in the evaluation *)
type t'
(** External type used outside of the module *)
val v : t -> t' * Report.t list
type expression
val call : pos -> T.keywords -> expression list -> t repr
(** Call for an instruction like [GT] or [*CLR] *)
val location : pos -> string -> t repr
(** Label for a loop *)
val comment : pos -> t repr
(** Comment *)
val expression : expression -> t repr
(** Raw expression *)
val if_ :
pos ->
(expression, t) clause ->
elifs:(expression, t) clause list ->
else_:(pos * t repr list) option ->
t repr
val act : pos -> label:expression -> t repr list -> t repr
val assign :
pos ->
(pos, expression) variable ->
T.assignation_operator ->
expression ->
t repr
end
module type Location = sig
type t
type instruction
val location : pos -> instruction list -> (t * Report.t list) repr
end
module type Analyzer = sig
module Expression : Expression
module Instruction :
Instruction with type expression = Expression.t' * Report.t list
module Location :
Location with type instruction = (Instruction.t' * Report.t list) repr
end
(** Helper module used in order to convert elements from the differents
representation levels.
Thoses functions are intended to be used in the menhir parser, in order to
limit the code in the mly file.
*)
module Helper (E : sig
type t
(** Internal type used in the evaluation *)
type t'
(** External type used outside of the module *)
val v : t -> t' * Report.t list
end) : sig
val v : E.t repr -> Report.t list -> E.t' * Report.t list
(** Convert an instruction from the internal representation *)
val v' : E.t -> E.t' * Report.t list
(** Convert an expression from the internal representation *)
val variable :
(pos, E.t) variable -> (pos, Report.t list -> E.t' * Report.t list) variable
val variable' : (pos, E.t) variable -> (pos, E.t' * Report.t list) variable
(** Convert a variable from the [Expression.t] into [Expression.t'] *)
end = struct
let v : E.t repr -> Report.t list -> E.t' * Report.t list =
fun v report ->
let value = v report in
E.v value
let v' : E.t -> E.t' * Report.t list = fun v -> E.v v
let variable :
(pos, E.t) variable ->
(pos, Report.t list -> E.t' * Report.t list) variable =
fun variable ->
let v' : E.t -> Report.t list -> E.t' * Report.t list =
fun t report ->
ignore report;
E.v t
in
{ variable with index = Option.map v' variable.index }
let variable' : (pos, E.t) variable -> (pos, E.t' * Report.t list) variable =
fun variable -> { variable with index = Option.map v' variable.index }
end
|