aboutsummaryrefslogtreecommitdiff
path: root/lib/syntax/S.ml
blob: 3b24aff7296837df46ed6bb074948317596d3135 (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
(** 
    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].*)

(** 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 *)

  type clause = pos * expression * t repr list

  val if_ : pos -> clause -> elifs: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 repr
  type instruction

  val location : pos -> instruction list -> 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' repr
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