2020-03-08 02:21:55 +03:00
|
|
|
(*
|
2020-04-16 18:47:35 +03:00
|
|
|
This file is part of the Catala compiler, a specification language for tax and social benefits
|
2020-03-08 02:21:55 +03:00
|
|
|
computation rules.
|
2021-05-27 19:56:47 +03:00
|
|
|
Copyright (C) 2020 Inria, contributors: Denis Merigoux <denis.merigoux@inria.fr>,
|
|
|
|
Emile Rolley <emile.rolley@tuta.io>
|
2020-03-08 02:21:55 +03:00
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
2021-03-09 20:48:58 +03:00
|
|
|
*)
|
2020-03-08 02:21:55 +03:00
|
|
|
|
|
|
|
%{
|
2022-11-21 12:46:17 +03:00
|
|
|
open Catala_utils
|
2021-05-15 02:16:08 +03:00
|
|
|
%}
|
2020-03-08 02:21:55 +03:00
|
|
|
|
2021-04-30 10:59:09 +03:00
|
|
|
%parameter<Localisation: sig
|
2021-08-19 19:26:06 +03:00
|
|
|
val lex_builtin: string -> Ast.builtin_expression option
|
2021-04-30 10:59:09 +03:00
|
|
|
end>
|
2020-04-03 23:34:11 +03:00
|
|
|
|
2021-05-15 02:16:08 +03:00
|
|
|
%type <Ast.source_file> source_file
|
2020-03-08 02:21:55 +03:00
|
|
|
|
2021-05-15 02:16:08 +03:00
|
|
|
%start source_file
|
2020-03-08 02:21:55 +03:00
|
|
|
|
2021-08-19 12:19:45 +03:00
|
|
|
(* The token is returned for every line of law text, make them right-associative
|
|
|
|
so that we concat them efficiently as much as possible. *)
|
|
|
|
%right LAW_TEXT
|
|
|
|
|
2020-03-08 02:21:55 +03:00
|
|
|
%%
|
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let typ_base :=
|
|
|
|
| INTEGER ; { (Integer, Pos.from_lpos $sloc) }
|
|
|
|
| BOOLEAN ; { (Boolean, Pos.from_lpos $sloc) }
|
|
|
|
| MONEY ; { (Money, Pos.from_lpos $sloc) }
|
|
|
|
| DURATION ; { (Duration, Pos.from_lpos $sloc) }
|
|
|
|
| TEXT ; { (Text, Pos.from_lpos $sloc) }
|
|
|
|
| DECIMAL ; { (Decimal, Pos.from_lpos $sloc) }
|
|
|
|
| DATE ; { (Date, Pos.from_lpos $sloc) }
|
|
|
|
| c = constructor ; {
|
2020-04-14 12:46:48 +03:00
|
|
|
let (s, _) = c in
|
2021-01-20 17:37:20 +03:00
|
|
|
(Named s, Pos.from_lpos $sloc)
|
2020-04-14 12:46:48 +03:00
|
|
|
}
|
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let typ :=
|
|
|
|
| t = typ_base ; {
|
2020-05-07 10:40:09 +03:00
|
|
|
let t, loc = t in
|
|
|
|
(Primitive t, loc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| COLLECTION ; t = typ ; {
|
2021-01-20 17:37:20 +03:00
|
|
|
(Collection t, Pos.from_lpos $sloc)
|
2020-04-14 12:46:48 +03:00
|
|
|
}
|
2020-03-08 07:01:26 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let qident :=
|
|
|
|
| b = separated_nonempty_list(DOT, ident) ; {
|
2021-01-20 17:37:20 +03:00
|
|
|
( b, Pos.from_lpos $sloc)
|
2020-04-14 18:58:36 +03:00
|
|
|
}
|
2020-04-14 18:29:50 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let atomic_expression :=
|
|
|
|
| q = IDENT ; {
|
2021-08-19 19:26:06 +03:00
|
|
|
(match Localisation.lex_builtin q with
|
|
|
|
| Some b -> Builtin b
|
|
|
|
| None -> Ident q),
|
2021-04-30 20:14:51 +03:00
|
|
|
Pos.from_lpos $sloc }
|
2022-12-13 19:55:16 +03:00
|
|
|
| l = literal ; { let (l, l_pos) = l in (Literal l, l_pos) }
|
|
|
|
| LPAREN ; e = expression ; RPAREN ; { e }
|
2020-04-14 18:29:50 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let small_expression :=
|
2022-12-13 19:57:21 +03:00
|
|
|
| ~ = atomic_expression ; <>
|
2022-12-13 19:55:16 +03:00
|
|
|
| e = small_expression ; DOT ; c = option(terminated(constructor,DOT)) ; i = ident ; {
|
2021-01-26 06:32:31 +03:00
|
|
|
(Dotted (e, c, i), Pos.from_lpos $sloc)
|
2020-07-01 00:15:14 +03:00
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| CARDINAL ; {
|
2022-10-21 16:47:17 +03:00
|
|
|
(Builtin Cardinal, Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| DECIMAL ; { Builtin ToDecimal, Pos.from_lpos $sloc }
|
|
|
|
| MONEY ; { Builtin ToMoney, Pos.from_lpos $sloc }
|
|
|
|
| LSQUARE ; l = separated_list(SEMICOLON, expression) ; RSQUARE ; {
|
2022-10-21 16:47:17 +03:00
|
|
|
(ArrayLit l, Pos.from_lpos $sloc)
|
|
|
|
}
|
2020-07-01 00:15:14 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let struct_content_field :=
|
|
|
|
| field = ident ; COLON ; e = logical_expression ; {
|
2020-07-01 00:15:14 +03:00
|
|
|
(field, e)
|
2020-04-14 20:13:20 +03:00
|
|
|
}
|
2020-04-14 18:29:50 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let enum_inject_content :=
|
|
|
|
| CONTENT ; e = small_expression ; { e }
|
2020-03-08 07:01:26 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let struct_inject_content :=
|
|
|
|
| LBRACKET ;
|
|
|
|
fields = nonempty_list(preceded(ALT, struct_content_field)) ;
|
|
|
|
RBRACKET ; {
|
|
|
|
fields
|
|
|
|
}
|
2020-07-01 00:15:14 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let struct_or_enum_inject :=
|
|
|
|
| enum = constructor ;
|
|
|
|
c = option(preceded(DOT, constructor)) ;
|
|
|
|
data = option(enum_inject_content) ; {
|
2021-01-26 18:38:10 +03:00
|
|
|
(* The fully qualified enum is actually the optional part, but it leads to shift/reduce conflicts.
|
|
|
|
We flip it here *)
|
|
|
|
match c with
|
|
|
|
| None -> (EnumInject(None, enum, data), Pos.from_lpos $sloc)
|
|
|
|
| Some c -> (EnumInject(Some enum, c, data), Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| c = constructor ;
|
|
|
|
fields = struct_inject_content ; {
|
|
|
|
(StructLit(c, fields), Pos.from_lpos $sloc)
|
|
|
|
}
|
2020-07-01 00:15:14 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let primitive_expression :=
|
2022-12-13 19:57:21 +03:00
|
|
|
| ~ = small_expression ; <>
|
2022-12-13 19:55:16 +03:00
|
|
|
| e = struct_or_enum_inject ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
e
|
|
|
|
}
|
2021-03-09 20:48:58 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let num_literal :=
|
|
|
|
| d = INT_LITERAL ; { (Int d, Pos.from_lpos $sloc) }
|
|
|
|
| d = DECIMAL_LITERAL ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
let (d1, d2) = d in
|
|
|
|
(Dec (d1, d2), Pos.from_lpos $sloc)
|
|
|
|
}
|
2020-04-14 20:13:20 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let unit_literal :=
|
|
|
|
| PERCENT ; { (Percent, Pos.from_lpos $sloc) }
|
|
|
|
| YEAR ; { (Year, Pos.from_lpos $sloc)}
|
|
|
|
| MONTH ; { (Month, Pos.from_lpos $sloc) }
|
|
|
|
| DAY ; { (Day, Pos.from_lpos $sloc) }
|
2020-04-11 19:16:15 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let literal :=
|
|
|
|
| l = num_literal; u = option(unit_literal) ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(LNumber (l, u), Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| money = MONEY_AMOUNT ; {
|
2020-04-25 16:17:44 +03:00
|
|
|
let (units, cents) = money in
|
2021-01-20 18:06:04 +03:00
|
|
|
(LMoneyAmount {
|
2020-04-25 16:17:44 +03:00
|
|
|
money_amount_units = units;
|
|
|
|
money_amount_cents = cents;
|
2021-01-20 17:37:20 +03:00
|
|
|
}, Pos.from_lpos $sloc)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| VERTICAL ; d = DATE_LITERAL ; VERTICAL ; {
|
2022-07-21 15:14:22 +03:00
|
|
|
let (y,m,d) = d in
|
2021-05-15 02:16:08 +03:00
|
|
|
(LDate {
|
|
|
|
literal_date_year = y;
|
|
|
|
literal_date_month = m;
|
|
|
|
literal_date_day = d;
|
2021-01-20 17:37:20 +03:00
|
|
|
}, Pos.from_lpos $sloc)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| TRUE ; { (LBool true, Pos.from_lpos $sloc) }
|
|
|
|
| FALSE ; { (LBool false, Pos.from_lpos $sloc) }
|
|
|
|
|
|
|
|
let compare_op :=
|
|
|
|
| LESSER ; { (Lt KPoly, Pos.from_lpos $sloc) }
|
|
|
|
| LESSER_EQUAL ; { (Lte KPoly, Pos.from_lpos $sloc) }
|
|
|
|
| GREATER ; { (Gt KPoly, Pos.from_lpos $sloc) }
|
|
|
|
| GREATER_EQUAL ; { (Gte KPoly, Pos.from_lpos $sloc) }
|
|
|
|
| EQUAL ; { (Eq, Pos.from_lpos $sloc) }
|
|
|
|
| NOT_EQUAL ; { (Neq, Pos.from_lpos $sloc) }
|
|
|
|
|
|
|
|
let scope_call_args :=
|
|
|
|
| WITH_V ;
|
|
|
|
LBRACKET ;
|
|
|
|
fields = list(preceded (ALT, struct_content_field)) ;
|
|
|
|
RBRACKET ; {
|
2022-12-07 20:31:08 +03:00
|
|
|
fields
|
|
|
|
}
|
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let minmax :=
|
|
|
|
| MAXIMUM ; { true }
|
|
|
|
| MINIMUM ; { false }
|
2022-12-12 18:02:07 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let base_expression :=
|
2022-12-13 19:57:21 +03:00
|
|
|
| ~ = primitive_expression ; <>
|
2022-12-13 19:55:16 +03:00
|
|
|
| e1 = small_expression ;
|
|
|
|
OF ;
|
|
|
|
e2 = base_expression ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(FunCall (e1, e2), Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| OUTPUT ; OF ;
|
|
|
|
c = constructor ;
|
|
|
|
fields = option(scope_call_args) ; {
|
2022-12-07 20:31:08 +03:00
|
|
|
let fields = Option.value ~default:[] fields in
|
2022-10-21 16:47:17 +03:00
|
|
|
(ScopeCall (c, fields), Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| e = primitive_expression ;
|
|
|
|
WITH ; c = constructor_binding ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(TestMatchCase (e, (c, Pos.from_lpos $sloc)), Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| e1 = primitive_expression ;
|
|
|
|
CONTAINS ;
|
|
|
|
e2 = base_expression ; {
|
2022-07-27 11:46:22 +03:00
|
|
|
(MemCollection (e2, e1), Pos.from_lpos $sloc)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| SUM ; typ = typ_base ;
|
|
|
|
OF ; coll = base_expression ; {
|
2022-12-12 18:02:07 +03:00
|
|
|
CollectionOp (AggregateSum { typ = Marked.unmark typ }, coll), Pos.from_lpos $sloc
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| f = primitive_expression ;
|
|
|
|
FOR ; i = ident ;
|
|
|
|
IN ; coll = base_expression ; {
|
2022-12-12 18:02:07 +03:00
|
|
|
CollectionOp (Map {f = i, f}, coll), Pos.from_lpos $sloc
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| max = minmax ;
|
|
|
|
OF ; coll = base_expression ;
|
|
|
|
OR ; IF ; COLLECTION ; IS ; EMPTY ; THEN ;
|
|
|
|
default = base_expression ; {
|
2022-12-12 18:02:07 +03:00
|
|
|
CollectionOp (AggregateExtremum { max; default }, coll), Pos.from_lpos $sloc
|
|
|
|
}
|
2020-03-08 07:12:12 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let unop :=
|
|
|
|
| NOT ; { (Not, Pos.from_lpos $sloc) }
|
|
|
|
| k = MINUS ; { (Minus k, Pos.from_lpos $sloc) }
|
2022-05-11 19:27:14 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let unop_expression :=
|
2022-12-13 19:57:21 +03:00
|
|
|
| ~ = base_expression ; <>
|
2022-12-13 19:55:16 +03:00
|
|
|
| op = unop ; e = unop_expression ; {
|
|
|
|
(Unop (op, e), Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-05-11 19:27:14 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let mult_op :=
|
|
|
|
| k = MULT ; { (Mult k, Pos.from_lpos $sloc) }
|
|
|
|
| k = DIV ; { (Div k, Pos.from_lpos $sloc) }
|
2021-05-15 02:16:08 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let mult_expression :=
|
2022-12-13 19:57:21 +03:00
|
|
|
| ~ = unop_expression ; <>
|
2022-12-13 19:55:16 +03:00
|
|
|
| e1 = mult_expression ;
|
|
|
|
binop = mult_op ;
|
|
|
|
e2 = unop_expression ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
|
|
|
|
}
|
2020-03-08 08:06:32 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let sum_op :=
|
|
|
|
| k = PLUS ; { (Add k, Pos.from_lpos $sloc) }
|
|
|
|
| k = MINUS ; { (Sub k, Pos.from_lpos $sloc) }
|
|
|
|
| PLUSPLUS ; { (Concat, Pos.from_lpos $sloc) }
|
2021-05-15 02:16:08 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let sum_expression :=
|
2022-12-13 19:57:21 +03:00
|
|
|
| ~ = mult_expression ; <>
|
2022-12-13 19:55:16 +03:00
|
|
|
| e1 = sum_expression ;
|
|
|
|
binop = sum_op ;
|
|
|
|
e2 = mult_expression ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
|
|
|
|
}
|
2021-03-09 20:48:58 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let logical_and_op :=
|
|
|
|
| AND ; { (And, Pos.from_lpos $sloc) }
|
2021-11-12 11:43:23 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let logical_or_op :=
|
|
|
|
| OR ; { (Or, Pos.from_lpos $sloc) }
|
|
|
|
| XOR ; { (Xor, Pos.from_lpos $sloc) }
|
2021-03-09 20:48:58 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let compare_expression :=
|
|
|
|
| ~ = sum_expression ; <>
|
|
|
|
| e1 = sum_expression ;
|
|
|
|
binop = compare_op ;
|
|
|
|
e2 = compare_expression ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
|
|
|
|
}
|
2021-03-09 20:48:58 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let logical_atom :=
|
|
|
|
| ~ = compare_expression ; <>
|
2021-11-12 11:43:23 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let logical_or_expression :=
|
|
|
|
| ~ = logical_atom ; <>
|
|
|
|
| e1 = logical_atom ;
|
|
|
|
binop = logical_or_op ;
|
|
|
|
e2 = logical_or_expression ; {
|
2021-11-12 11:43:23 +03:00
|
|
|
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
|
|
|
|
}
|
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let logical_expression :=
|
2022-12-13 19:57:21 +03:00
|
|
|
| ~ = logical_or_expression ; <>
|
2022-12-13 19:55:16 +03:00
|
|
|
| e1 = logical_or_expression ;
|
|
|
|
binop = logical_and_op ;
|
|
|
|
e2 = logical_expression ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
|
|
|
|
}
|
2021-03-09 20:48:58 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let maybe_qualified_constructor :=
|
|
|
|
| c_or_path = constructor ;
|
|
|
|
c = option(preceded(DOT, constructor)) ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
match c with
|
2021-01-26 19:41:20 +03:00
|
|
|
| None -> (None, c_or_path)
|
|
|
|
| Some c -> (Some c_or_path, c)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2021-01-26 19:41:20 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let optional_binding :=
|
2021-05-15 02:16:08 +03:00
|
|
|
| { ([], None)}
|
2022-12-13 19:55:16 +03:00
|
|
|
| OF ; i = ident ; {([], Some i)}
|
|
|
|
| OF ;
|
|
|
|
c = maybe_qualified_constructor ;
|
|
|
|
cs_and_i = constructor_binding ; {
|
2020-04-14 20:13:20 +03:00
|
|
|
let (cs, i) = cs_and_i in
|
|
|
|
(c::cs, i)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2020-03-08 08:49:29 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let constructor_binding :=
|
|
|
|
| c = maybe_qualified_constructor ;
|
|
|
|
cs_and_i = optional_binding ; {
|
|
|
|
let (cs, i) = cs_and_i in
|
|
|
|
(c::cs, i)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2020-03-08 08:06:32 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let match_arm :=
|
|
|
|
| WILDCARD ;
|
|
|
|
COLON ;
|
|
|
|
e = logical_expression ; {
|
|
|
|
(WildCard (e), Pos.from_lpos $sloc)
|
|
|
|
}
|
|
|
|
| pat = constructor_binding ;
|
|
|
|
COLON ;
|
|
|
|
e = logical_expression ; {
|
|
|
|
(MatchCase {
|
2021-05-15 02:16:08 +03:00
|
|
|
(* DM 14/04/2020 : I can't have the $sloc in constructor_binding... *)
|
|
|
|
match_case_pattern = (pat, Pos.from_lpos $sloc);
|
2021-06-01 19:56:03 +03:00
|
|
|
match_case_expr = e;
|
2022-12-13 19:55:16 +03:00
|
|
|
}, Pos.from_lpos $sloc)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2020-03-08 08:06:32 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let match_arms :=
|
|
|
|
| ALT ; a = match_arm ; arms = match_arms ; {
|
|
|
|
let (arms, _) = arms in
|
|
|
|
(a::arms, Pos.from_lpos $sloc)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| { ([], Pos.from_lpos $sloc) }
|
2020-03-08 08:06:32 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let let_expression :=
|
2022-12-13 19:57:21 +03:00
|
|
|
| ~ = logical_expression ; <>
|
2022-12-13 19:55:16 +03:00
|
|
|
| EXISTS ; i = ident ;
|
|
|
|
IN ; coll = compare_expression ;
|
|
|
|
SUCH ; THAT ; predicate = compare_expression ; {
|
2022-12-12 18:02:07 +03:00
|
|
|
CollectionOp (Exists {predicate = i, predicate}, coll), Pos.from_lpos $sloc
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| FOR ; ALL ; i = ident ;
|
|
|
|
IN ; coll = compare_expression ;
|
|
|
|
WE_HAVE ; predicate = compare_expression ; {
|
2022-12-12 18:02:07 +03:00
|
|
|
CollectionOp (Forall {predicate = i, predicate}, coll), Pos.from_lpos $sloc
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| MATCH ; e = primitive_expression ;
|
|
|
|
WITH ; arms = match_arms ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(MatchWith (e, arms), Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| IF ; e1 = let_expression ;
|
|
|
|
THEN ; e2 = let_expression ;
|
|
|
|
ELSE ; e3 = let_expression ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(IfThenElse (e1, e2, e3), Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| LET ; id = ident ;
|
|
|
|
DEFINED_AS ; e1 = let_expression ;
|
|
|
|
IN ; e2 = let_expression ; {
|
2022-07-26 14:40:43 +03:00
|
|
|
(LetIn (id, e1, e2), Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-12 18:02:07 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let expression :=
|
2022-12-13 19:57:21 +03:00
|
|
|
| ~ = let_expression ; <>
|
2022-12-13 19:55:16 +03:00
|
|
|
| i = ident ;
|
|
|
|
IN ; coll = compare_expression ;
|
|
|
|
SUCH ; THAT ; f = compare_expression ; {
|
2022-12-12 18:02:07 +03:00
|
|
|
CollectionOp (Filter {f = i, f}, coll), Pos.from_lpos $sloc
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| i = ident ;
|
|
|
|
IN ; coll = compare_expression ;
|
|
|
|
SUCH ; THAT ; f = compare_expression ;
|
|
|
|
IS ; max = minmax ;
|
|
|
|
OR ; IF ; COLLECTION ; IS ; EMPTY ; THEN ; default = expression ; {
|
2022-12-12 18:02:07 +03:00
|
|
|
CollectionOp (AggregateArgExtremum { max; default; f = i, f }, coll),
|
|
|
|
Pos.from_lpos $sloc
|
|
|
|
}
|
2021-05-15 02:16:08 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let condition :=
|
|
|
|
| UNDER_CONDITION ; e = expression ; { e }
|
2020-03-08 07:01:26 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let condition_consequence :=
|
|
|
|
| cond = condition ; CONSEQUENCE ; { cond }
|
2020-03-08 08:30:05 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let rule_expr :=
|
|
|
|
| i = qident ;
|
|
|
|
p = option(definition_parameters) ; {
|
|
|
|
(i, p)
|
|
|
|
}
|
2020-04-14 20:16:40 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let rule_consequence :=
|
|
|
|
| flag = option(NOT); FILLED ; {
|
2020-08-07 11:57:57 +03:00
|
|
|
let b = match flag with Some _ -> false | None -> true in
|
2021-01-20 17:37:20 +03:00
|
|
|
(b, Pos.from_lpos $sloc)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2020-08-07 11:57:57 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let rule :=
|
|
|
|
| label = option(label) ;
|
|
|
|
except = option(exception_to) ;
|
|
|
|
RULE ;
|
|
|
|
name_and_param = rule_expr ;
|
|
|
|
cond = option(condition_consequence) ;
|
|
|
|
state = option(state) ;
|
|
|
|
consequence = rule_consequence ; {
|
|
|
|
let (name, param_applied) = name_and_param in
|
|
|
|
let cons : bool Marked.pos = consequence in
|
|
|
|
let rule_exception = match except with
|
|
|
|
| None -> NotAnException
|
|
|
|
| Some x -> x
|
|
|
|
in
|
|
|
|
{
|
|
|
|
rule_label = label;
|
|
|
|
rule_exception_to = rule_exception;
|
|
|
|
rule_parameter = param_applied;
|
|
|
|
rule_condition = cond;
|
|
|
|
rule_name = name;
|
|
|
|
rule_id = Shared_ast.RuleName.fresh
|
|
|
|
(String.concat "." (List.map (fun i -> Marked.unmark i) (Marked.unmark name)),
|
|
|
|
Pos.from_lpos $sloc);
|
|
|
|
rule_consequence = cons;
|
|
|
|
rule_state = state;
|
|
|
|
}, $sloc
|
|
|
|
}
|
|
|
|
|
|
|
|
let definition_parameters :=
|
|
|
|
| OF ; i = ident ; { i }
|
|
|
|
|
|
|
|
let label :=
|
|
|
|
| LABEL ; i = ident ; { i }
|
|
|
|
|
|
|
|
let state :=
|
|
|
|
| STATE ; s = ident ; { s }
|
|
|
|
|
|
|
|
let exception_to :=
|
|
|
|
| EXCEPTION ; i = option(ident) ; {
|
|
|
|
match i with
|
|
|
|
| None -> UnlabeledException
|
|
|
|
| Some x -> ExceptionToLabel x
|
|
|
|
}
|
|
|
|
|
|
|
|
let definition :=
|
|
|
|
| label = option(label);
|
|
|
|
except = option(exception_to) ;
|
|
|
|
DEFINITION ;
|
|
|
|
name = qident ;
|
|
|
|
param = option(definition_parameters) ;
|
|
|
|
state = option(state) ;
|
|
|
|
cond = option(condition_consequence) ;
|
|
|
|
DEFINED_AS ;
|
|
|
|
e = expression ; {
|
|
|
|
let def_exception = match except with
|
|
|
|
| None -> NotAnException
|
|
|
|
| Some x -> x
|
|
|
|
in
|
|
|
|
{
|
|
|
|
definition_label = label;
|
|
|
|
definition_exception_to = def_exception;
|
|
|
|
definition_name = name;
|
|
|
|
definition_parameter = param;
|
|
|
|
definition_condition = cond;
|
|
|
|
definition_id =
|
|
|
|
Shared_ast.RuleName.fresh
|
2022-05-30 12:20:48 +03:00
|
|
|
(String.concat "." (List.map (fun i -> Marked.unmark i) (Marked.unmark name)),
|
2021-11-28 15:09:44 +03:00
|
|
|
Pos.from_lpos $sloc);
|
2022-12-13 19:55:16 +03:00
|
|
|
definition_expr = e;
|
|
|
|
definition_state = state;
|
|
|
|
}, $sloc
|
|
|
|
}
|
|
|
|
|
|
|
|
let variation_type :=
|
|
|
|
| INCREASING ; { (Increasing, Pos.from_lpos $sloc) }
|
|
|
|
| DECREASING ; { (Decreasing, Pos.from_lpos $sloc) }
|
|
|
|
|
|
|
|
let assertion_base :=
|
|
|
|
| e = expression ; { let (e, _) = e in (e, Pos.from_lpos $sloc) }
|
|
|
|
|
|
|
|
let assertion :=
|
|
|
|
| cond = option(condition_consequence) ;
|
|
|
|
base = assertion_base ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(Assertion {
|
|
|
|
assertion_condition = cond;
|
2020-04-25 15:21:26 +03:00
|
|
|
assertion_content = base;
|
2021-03-09 20:48:58 +03:00
|
|
|
})
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| FIXED ; q = qident ; BY ; i = ident ; {
|
|
|
|
MetaAssertion (FixedBy (q, i))
|
|
|
|
}
|
|
|
|
| VARIES ; q = qident ;
|
|
|
|
WITH_V ; e = base_expression ;
|
|
|
|
t = option(variation_type) ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
MetaAssertion (VariesWith (q, e, t))
|
|
|
|
}
|
2020-03-08 08:06:32 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let scope_item :=
|
|
|
|
| r = rule ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
let (r, _) = r in (Rule r, Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| d = definition ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
let (d, _) = d in (Definition d, Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| ASSERTION ; contents = assertion ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(contents, Pos.from_lpos $sloc)
|
|
|
|
}
|
2020-03-08 06:28:45 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let ident :=
|
|
|
|
| i = IDENT ; {
|
2021-08-19 19:26:06 +03:00
|
|
|
match Localisation.lex_builtin i with
|
|
|
|
| Some _ ->
|
2022-12-13 19:55:16 +03:00
|
|
|
Errors.raise_spanned_error
|
|
|
|
(Pos.from_lpos $sloc)
|
|
|
|
"Reserved builtin name"
|
2021-08-19 19:26:06 +03:00
|
|
|
| None ->
|
2022-12-13 19:55:16 +03:00
|
|
|
(i, Pos.from_lpos $sloc)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2020-04-14 12:46:48 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let condition_pos :=
|
|
|
|
| CONDITION ; { Pos.from_lpos $sloc }
|
2020-04-14 12:46:48 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let struct_scope_base :=
|
|
|
|
| DATA ; i = ident ;
|
|
|
|
CONTENT ; t = typ ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
let t, pos = t in
|
|
|
|
(i, (Data t, pos))
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| pos = condition_pos ; i = ident ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(i, (Condition, pos))
|
|
|
|
}
|
2020-04-03 23:58:34 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let struct_scope_func :=
|
|
|
|
| DEPENDS ; t = typ ; { t }
|
2020-04-03 23:58:34 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let struct_scope :=
|
|
|
|
| name_and_typ = struct_scope_base ;
|
|
|
|
func_typ = option(struct_scope_func) ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
let (name, typ) = name_and_typ in
|
|
|
|
let (typ, typ_pos) = typ in
|
2022-12-13 19:55:16 +03:00
|
|
|
{
|
2021-05-15 02:16:08 +03:00
|
|
|
struct_decl_field_name = name;
|
2020-04-14 13:34:09 +03:00
|
|
|
struct_decl_field_typ = match func_typ with
|
|
|
|
| None -> (Base typ, typ_pos)
|
2022-12-13 19:55:16 +03:00
|
|
|
| Some (arg_typ, arg_pos) ->
|
|
|
|
Func {
|
|
|
|
arg_typ = (Data arg_typ, arg_pos);
|
|
|
|
return_typ = (typ, typ_pos);
|
|
|
|
}, Pos.from_lpos $sloc ;
|
|
|
|
}, Pos.from_lpos $sloc
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2020-04-03 23:58:34 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let scope_decl_item_attribute_input :=
|
|
|
|
| CONTEXT ; { Context, Pos.from_lpos $sloc }
|
|
|
|
| INPUT ; { Input, Pos.from_lpos $sloc }
|
2022-01-27 20:03:47 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let scope_decl_item_attribute_output :=
|
|
|
|
| OUTPUT ; { true, Pos.from_lpos $sloc }
|
2022-02-07 12:30:36 +03:00
|
|
|
| { false, Pos.from_lpos $sloc }
|
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let scope_decl_item_attribute :=
|
|
|
|
| input = scope_decl_item_attribute_input ;
|
|
|
|
output = scope_decl_item_attribute_output ; {
|
2022-02-07 12:30:36 +03:00
|
|
|
{
|
|
|
|
scope_decl_context_io_input = input;
|
2022-02-07 14:04:48 +03:00
|
|
|
scope_decl_context_io_output = output
|
2022-02-07 12:30:36 +03:00
|
|
|
}
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| INTERNAL ; {
|
2022-02-07 14:04:48 +03:00
|
|
|
{
|
|
|
|
scope_decl_context_io_input = (Internal, Pos.from_lpos $sloc);
|
|
|
|
scope_decl_context_io_output = (false, Pos.from_lpos $sloc)
|
|
|
|
}
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| OUTPUT ; {
|
2022-02-07 14:04:48 +03:00
|
|
|
{
|
|
|
|
scope_decl_context_io_input = (Internal, Pos.from_lpos $sloc);
|
|
|
|
scope_decl_context_io_output = (true, Pos.from_lpos $sloc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-07 12:30:36 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let scope_decl_item :=
|
|
|
|
| attr = scope_decl_item_attribute ;
|
|
|
|
i = ident ;
|
|
|
|
CONTENT ; t = typ ;
|
|
|
|
func_typ = option(struct_scope_func) ;
|
|
|
|
states = list(state) ; {
|
|
|
|
(ContextData {
|
2021-05-15 02:16:08 +03:00
|
|
|
scope_decl_context_item_name = i;
|
2022-01-27 20:03:47 +03:00
|
|
|
scope_decl_context_item_attribute = attr;
|
2020-05-14 22:19:46 +03:00
|
|
|
scope_decl_context_item_typ =
|
2022-02-28 16:33:07 +03:00
|
|
|
(let (typ, typ_pos) = t in
|
2020-04-14 13:54:40 +03:00
|
|
|
match func_typ with
|
2020-05-07 10:40:09 +03:00
|
|
|
| None -> (Base (Data typ), typ_pos)
|
2022-12-13 19:55:16 +03:00
|
|
|
| Some (arg_typ, arg_pos) ->
|
|
|
|
Func {
|
|
|
|
arg_typ = (Data arg_typ, arg_pos);
|
|
|
|
return_typ = (Data typ, typ_pos);
|
|
|
|
}, Pos.from_lpos $sloc);
|
2022-02-28 16:33:07 +03:00
|
|
|
scope_decl_context_item_states = states;
|
2022-12-13 19:55:16 +03:00
|
|
|
}, Pos.from_lpos $sloc)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| i = ident ; SCOPE ; c = constructor ; {
|
|
|
|
(ContextScope{
|
2021-05-15 02:16:08 +03:00
|
|
|
scope_decl_context_scope_name = i;
|
|
|
|
scope_decl_context_scope_sub_scope = c;
|
2022-02-07 12:30:36 +03:00
|
|
|
scope_decl_context_scope_attribute = {
|
|
|
|
scope_decl_context_io_input = (Internal, Pos.from_lpos $sloc);
|
|
|
|
scope_decl_context_io_output = (false, Pos.from_lpos $sloc);
|
|
|
|
};
|
2022-12-13 19:55:16 +03:00
|
|
|
}, Pos.from_lpos $sloc)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| attr = scope_decl_item_attribute ;
|
|
|
|
i = ident ;
|
|
|
|
_condition = CONDITION ;
|
|
|
|
func_typ = option(struct_scope_func) ;
|
|
|
|
states = list(state) ; {
|
|
|
|
ContextData {
|
2021-05-15 02:16:08 +03:00
|
|
|
scope_decl_context_item_name = i;
|
2022-01-27 20:03:47 +03:00
|
|
|
scope_decl_context_item_attribute = attr;
|
2021-05-15 02:16:08 +03:00
|
|
|
scope_decl_context_item_typ =
|
2022-02-28 16:33:07 +03:00
|
|
|
(match func_typ with
|
2021-05-15 02:16:08 +03:00
|
|
|
| None -> (Base (Condition), Pos.from_lpos $loc(_condition))
|
2022-12-13 19:55:16 +03:00
|
|
|
| Some (arg_typ, arg_pos) ->
|
|
|
|
Func {
|
|
|
|
arg_typ = (Data arg_typ, arg_pos);
|
|
|
|
return_typ = (Condition, Pos.from_lpos $loc(_condition));
|
|
|
|
}, Pos.from_lpos $sloc);
|
2022-02-28 16:33:07 +03:00
|
|
|
scope_decl_context_item_states = states;
|
2022-12-13 19:55:16 +03:00
|
|
|
}, Pos.from_lpos $sloc
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2020-04-03 23:58:34 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let enum_decl_line_payload :=
|
|
|
|
| CONTENT ; t = typ ; { let (t, t_pos) = t in (Base (Data t), t_pos) }
|
2020-04-10 13:55:18 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let enum_decl_line :=
|
|
|
|
| ALT ; c = constructor ;
|
|
|
|
t = option(enum_decl_line_payload) ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
({
|
|
|
|
enum_decl_case_name = c;
|
2020-04-14 13:34:09 +03:00
|
|
|
enum_decl_case_typ = t;
|
2021-05-15 02:16:08 +03:00
|
|
|
}, Pos.from_lpos $sloc)
|
|
|
|
}
|
2020-04-14 12:46:48 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let constructor :=
|
|
|
|
| c = CONSTRUCTOR ; { (c, Pos.from_lpos $sloc) }
|
2020-04-10 13:55:18 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let scope_use_condition :=
|
|
|
|
| UNDER_CONDITION ; e = expression ; { e }
|
2020-05-18 12:29:22 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let code_item :=
|
|
|
|
| SCOPE ; c = constructor ;
|
|
|
|
e = option(scope_use_condition) ;
|
|
|
|
COLON ; items = nonempty_list(scope_item) ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(ScopeUse {
|
|
|
|
scope_use_name = c;
|
2020-05-18 12:29:22 +03:00
|
|
|
scope_use_condition = e;
|
2020-05-14 22:19:46 +03:00
|
|
|
scope_use_items = items;
|
2021-05-15 02:16:08 +03:00
|
|
|
}, Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| DECLARATION ; STRUCT ; c = constructor ;
|
|
|
|
COLON ; scopes = list(struct_scope) ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(StructDecl {
|
|
|
|
struct_decl_name = c;
|
2020-05-14 22:19:46 +03:00
|
|
|
struct_decl_fields = scopes;
|
2021-05-15 02:16:08 +03:00
|
|
|
}, Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| DECLARATION ; SCOPE ; c = constructor ;
|
|
|
|
COLON ; context = nonempty_list(scope_decl_item) ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(ScopeDecl {
|
|
|
|
scope_decl_name = c;
|
|
|
|
scope_decl_context = context;
|
|
|
|
}, Pos.from_lpos $sloc)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| DECLARATION ; ENUM ; c = constructor ;
|
|
|
|
COLON ; cases = list(enum_decl_line) ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
(EnumDecl {
|
|
|
|
enum_decl_name = c;
|
2020-04-14 13:34:09 +03:00
|
|
|
enum_decl_cases = cases;
|
2021-05-15 02:16:08 +03:00
|
|
|
}, Pos.from_lpos $sloc)
|
|
|
|
}
|
2021-03-09 20:48:58 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let code :=
|
|
|
|
| code = list(code_item) ; { (code, Pos.from_lpos $sloc) }
|
2021-03-09 20:48:58 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let metadata_block :=
|
|
|
|
| BEGIN_METADATA ; option(law_text) ;
|
|
|
|
code_and_pos = code ;
|
|
|
|
text = END_CODE ; {
|
2022-08-16 12:46:20 +03:00
|
|
|
let (code, _) = code_and_pos in
|
|
|
|
(code, (text, Pos.from_lpos $sloc))
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let law_heading :=
|
|
|
|
| title = LAW_HEADING ; {
|
2022-09-07 18:14:22 +03:00
|
|
|
let (title, id, is_archive, precedence) = title in {
|
2021-05-15 02:16:08 +03:00
|
|
|
law_heading_name = (title, Pos.from_lpos $sloc);
|
|
|
|
law_heading_id = id;
|
2022-09-07 18:14:22 +03:00
|
|
|
law_heading_is_archive = is_archive;
|
2020-10-04 02:25:37 +03:00
|
|
|
law_heading_precedence = precedence;
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let law_text :=
|
|
|
|
| lines = nonempty_list(LAW_TEXT) ; { String.trim (String.concat "" lines) }
|
2021-05-15 02:16:08 +03:00
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let source_file_item :=
|
|
|
|
| text = law_text ; { LawText text }
|
|
|
|
| BEGIN_CODE ;
|
|
|
|
code_and_pos = code ;
|
|
|
|
text = END_CODE ; {
|
2022-08-10 19:04:44 +03:00
|
|
|
let (code, _) = code_and_pos in
|
2022-08-10 11:45:49 +03:00
|
|
|
CodeBlock (code, (text, Pos.from_lpos $sloc), false)
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| heading = law_heading ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
LawHeading (heading, [])
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| code = metadata_block ; {
|
2021-05-15 02:16:08 +03:00
|
|
|
let (code, source_repr) = code in
|
|
|
|
CodeBlock (code, source_repr, true)
|
|
|
|
}
|
2022-12-13 19:55:16 +03:00
|
|
|
| BEGIN_DIRECTIVE ; LAW_INCLUDE ; COLON ;
|
|
|
|
args = nonempty_list(DIRECTIVE_ARG) ;
|
|
|
|
page = option(AT_PAGE) ;
|
|
|
|
END_DIRECTIVE ; {
|
2021-08-17 16:49:48 +03:00
|
|
|
let filename = String.trim (String.concat "" args) in
|
|
|
|
let pos = Pos.from_lpos $sloc in
|
2022-12-13 19:55:16 +03:00
|
|
|
let jorftext = Re.Pcre.regexp "JORFTEXT\\d; {12}" in
|
2021-08-17 16:49:48 +03:00
|
|
|
if Re.Pcre.pmatch ~rex:jorftext filename && page = None then
|
|
|
|
LawInclude (Ast.LegislativeText (filename, pos))
|
|
|
|
else if Filename.extension filename = ".pdf" || page <> None then
|
|
|
|
LawInclude (Ast.PdfFile ((filename, pos), page))
|
|
|
|
else
|
|
|
|
LawInclude (Ast.CatalaFile (filename, pos))
|
2021-05-15 02:16:08 +03:00
|
|
|
}
|
|
|
|
|
2022-12-13 19:55:16 +03:00
|
|
|
let source_file :=
|
|
|
|
| hd = source_file_item ; tl = source_file ; { hd::tl }
|
|
|
|
| EOF ; { [] }
|