aboutsummaryrefslogtreecommitdiff
path: root/lib/syntax/S.ml
blob: 3d868816c181d7ea11dc5898116f07b06eaddaeb (plain)
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
(** 
    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 * Report.t list

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 * Report.t list -> t' * Report.t list
  val ident : (pos, t repr) variable -> t repr

  (*
        Basic values, text, number…
   *)

  val integer : pos -> string -> t repr
  val literal : pos -> string -> t repr

  val function_ : pos -> T.function_ -> t repr list -> t repr
  (** Call a function. The functions list is hardcoded in lib/lexer.mll *)

  val uoperator : pos -> T.uoperator -> t repr -> t repr
  (** Unary operator like [-123] or [+'Text']*)

  val boperator : pos -> T.boperator -> t repr -> t repr -> t repr
  (** 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 * Report.t list -> 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_:t repr list ->
    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 repr list -> t repr
end

module type Analyzer = sig
  module Expression : Expression
  module Instruction : Instruction with type expression = Expression.t' repr
  module Location : Location with type instruction = Instruction.t'
end

(** Helper module used in order to convert elements from the differents
    representation levels *)
module Helper (E : sig
  type t
  (** Internal type used in the evaluation *)

  type t'
  (** External type used outside of the module *)

  val v : t * Report.t list -> t' * Report.t list
end) : sig
  val v : E.t repr -> E.t' repr

  val variable : (pos, E.t repr) variable -> (pos, E.t' repr) variable
  (** Convert a variable from the [Expression.t] into [Expression.t'] *)
end = struct
  let v : E.t repr -> E.t' repr =
   fun v report ->
    let value, report = v report in
    E.v (value, report)

  let variable : (pos, E.t repr) variable -> (pos, E.t' repr) variable =
   fun variable -> { variable with index = Option.map v variable.index }
end