mirror of
https://github.com/CatalaLang/catala.git
synced 2024-09-20 00:41:05 +03:00
Improved architecture
This commit is contained in:
parent
12cee7627b
commit
56bc45db9d
@ -1,6 +1,6 @@
|
|||||||
(lang dune 1.10)
|
(lang dune 1.10)
|
||||||
(name lawspec)
|
(name lawspec)
|
||||||
(version 1.0.2)
|
(version 0.1)
|
||||||
(generate_opam_files true)
|
(generate_opam_files true)
|
||||||
|
|
||||||
(source (uri git+https://gitlab.inria.fr/verifisc/lawspec.git))
|
(source (uri git+https://gitlab.inria.fr/verifisc/lawspec.git))
|
||||||
@ -22,6 +22,7 @@
|
|||||||
(ANSITerminal (>= 0.8.2))
|
(ANSITerminal (>= 0.8.2))
|
||||||
(sedlex (>= 2.1))
|
(sedlex (>= 2.1))
|
||||||
(menhirLib (>= 20200211))
|
(menhirLib (>= 20200211))
|
||||||
|
(dune-build-info (>= 2.0.1))
|
||||||
(dune (and :build ))
|
(dune (and :build ))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -11,7 +11,7 @@ authors: ["Denis Merigoux"]
|
|||||||
bug-reports: "https://gitlab.inria.fr/verifisc/lawspec/issues"
|
bug-reports: "https://gitlab.inria.fr/verifisc/lawspec/issues"
|
||||||
homepage: "https://gitlab.inria.fr/verifisc/lawspec"
|
homepage: "https://gitlab.inria.fr/verifisc/lawspec"
|
||||||
license: "Apache2"
|
license: "Apache2"
|
||||||
version: "1.0.2"
|
version: "0.1"
|
||||||
dev-repo: "git+https://gitlab.inria.fr/verifisc/lawspec.git"
|
dev-repo: "git+https://gitlab.inria.fr/verifisc/lawspec.git"
|
||||||
synopsis: "Low-level language for tax code specification"
|
synopsis: "Low-level language for tax code specification"
|
||||||
description: """
|
description: """
|
||||||
@ -23,5 +23,6 @@ depends: [
|
|||||||
"ANSITerminal" {>= "0.8.2"}
|
"ANSITerminal" {>= "0.8.2"}
|
||||||
"sedlex" {>= "2.1"}
|
"sedlex" {>= "2.1"}
|
||||||
"menhirLib" {>= "20200211"}
|
"menhirLib" {>= "20200211"}
|
||||||
|
"dune-build-info" {>= "2.0.1"}
|
||||||
"dune" {build}
|
"dune" {build}
|
||||||
]
|
]
|
||||||
|
9
src/dune
9
src/dune
@ -1,9 +1,6 @@
|
|||||||
(include_subdirs unqualified)
|
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
(name main)
|
(name main)
|
||||||
(public_name lawspec)
|
|
||||||
(package lawspec)
|
(package lawspec)
|
||||||
(libraries ANSITerminal sedlex menhirLib re)
|
(public_name lawspec)
|
||||||
(preprocess (pps sedlex.ppx))
|
(libraries lawspec)
|
||||||
)
|
(preprocess (pps sedlex.ppx)))
|
||||||
|
@ -22,19 +22,67 @@ let source_files : string list ref = ref []
|
|||||||
(** Prints debug information *)
|
(** Prints debug information *)
|
||||||
let debug_flag = ref false
|
let debug_flag = ref false
|
||||||
|
|
||||||
let parse_cli_args () =
|
open Cmdliner
|
||||||
(* Code block to retrieve and parse command-line arguments. *)
|
|
||||||
let speclist = Arg.align [
|
|
||||||
("--debug", Arg.Set debug_flag,
|
|
||||||
" Prints debugging information");
|
|
||||||
]
|
|
||||||
in let usage_msg =
|
|
||||||
"Parser and compiler for Lawspec."
|
|
||||||
in
|
|
||||||
let anon_func (file: string) : unit =
|
|
||||||
source_files := file::!source_files
|
|
||||||
in Arg.parse speclist anon_func usage_msg
|
|
||||||
|
|
||||||
|
let files = Arg.(non_empty & pos_all file [] & info [] ~docv:"FILES" ~doc:"Lawspec files to be compiled")
|
||||||
|
|
||||||
|
let debug = Arg.(value & flag & info [ "debug"; "d" ] ~doc:"Prints debug information")
|
||||||
|
|
||||||
|
let backend =
|
||||||
|
Arg.(
|
||||||
|
required
|
||||||
|
& opt (some string) None
|
||||||
|
& info [ "backend"; "b" ] ~docv:"BACKEND"
|
||||||
|
~doc:"Backend selection: TeX")
|
||||||
|
|
||||||
|
let output =
|
||||||
|
Arg.(
|
||||||
|
required
|
||||||
|
& opt (some string) None
|
||||||
|
& info [ "output"; "o" ] ~docv:"OUTPUT"
|
||||||
|
~doc:
|
||||||
|
"$(i, OUTPUT) is the file that will contain the extracted function (for compiler \
|
||||||
|
backends)")
|
||||||
|
|
||||||
|
let lawspec_t f =
|
||||||
|
Term.(const f $ files $ debug $ backend $ output)
|
||||||
|
|
||||||
|
let info =
|
||||||
|
let doc =
|
||||||
|
"Compiler for Lawspec, a specification language for tax and social benefits computation rules."
|
||||||
|
in
|
||||||
|
let man =
|
||||||
|
[
|
||||||
|
`S Manpage.s_description;
|
||||||
|
`P
|
||||||
|
"The M language is used by the DGFiP to encode the rules describing the computation of the \
|
||||||
|
French income tax. An M program consists in several *.m files in no particular order. \
|
||||||
|
$(tname) will parse all the rules contained in those files that correspond to a \
|
||||||
|
particular application tag. Then, it will extract from this set of rules an \
|
||||||
|
user-specified function, than can be interpreted with a command-line prompt or compiled \
|
||||||
|
to a function in the language of your choice.";
|
||||||
|
`S Manpage.s_authors;
|
||||||
|
`P "Denis Merigoux <denis.merigoux@inria.fr>";
|
||||||
|
`S Manpage.s_examples;
|
||||||
|
`P "Typical usage:";
|
||||||
|
`Pre "lawspec -b LaTeX file.lsp";
|
||||||
|
`S Manpage.s_bugs;
|
||||||
|
`P "Please file bug reports at https://gitlab.inria.fr/verifisc/lawspec/issues";
|
||||||
|
]
|
||||||
|
in
|
||||||
|
let exits =
|
||||||
|
Term.default_exits
|
||||||
|
@ [
|
||||||
|
Term.exit_info ~doc:"on parsing error." 1;
|
||||||
|
Term.exit_info ~doc:"on typechecking error." 2;
|
||||||
|
]
|
||||||
|
in
|
||||||
|
Term.info "lawspec"
|
||||||
|
~version:
|
||||||
|
( match Build_info.V1.version () with
|
||||||
|
| None -> "n/a"
|
||||||
|
| Some v -> Build_info.V1.Version.to_string v )
|
||||||
|
~doc ~exits ~man
|
||||||
|
|
||||||
|
|
||||||
(**{1 Terminal formatting }*)
|
(**{1 Terminal formatting }*)
|
53
src/lawspec/driver.ml
Normal file
53
src/lawspec/driver.ml
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
(*
|
||||||
|
This file is part of the Lawspec compiler, a specification language for tax and social benefits
|
||||||
|
computation rules.
|
||||||
|
Copyright (C) 2019 Inria, contributor: Denis Merigoux <denis.merigoux@inria.fr>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*)
|
||||||
|
|
||||||
|
open Cli
|
||||||
|
|
||||||
|
(** Entry function for the executable. Returns a negative number in case of error. *)
|
||||||
|
let driver
|
||||||
|
(source_files : string list)
|
||||||
|
(debug: bool)
|
||||||
|
(_backend: string)
|
||||||
|
(_output_file : string)
|
||||||
|
: int =
|
||||||
|
Cli.debug_flag := debug;
|
||||||
|
Cli.debug_print "Reading files...";
|
||||||
|
let program = ref [] in
|
||||||
|
List.iter (fun source_file ->
|
||||||
|
let input = open_in source_file in
|
||||||
|
Cli.debug_print (Printf.sprintf "Parsing %s" source_file);
|
||||||
|
let lexbuf = Sedlex_menhir.create_lexbuf ~file:(Filename.basename source_file) (Sedlexing.Utf8.from_channel input) in
|
||||||
|
try
|
||||||
|
Parse_utils.current_file := source_file;
|
||||||
|
let commands = Sedlex_menhir.sedlex_with_menhir Lexer.lexer Parser.source_file lexbuf in
|
||||||
|
program := commands::!program;
|
||||||
|
close_in input
|
||||||
|
with
|
||||||
|
| Errors.LexingError msg | Errors.ParsingError msg ->
|
||||||
|
error_print msg
|
||||||
|
| Sedlex_menhir.ParseError msg -> begin
|
||||||
|
error_print
|
||||||
|
(Printf.sprintf "Parser error: %s" msg);
|
||||||
|
close_in input;
|
||||||
|
exit (-1)
|
||||||
|
end
|
||||||
|
) source_files;
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
let main () =
|
||||||
|
Cmdliner.Term.exit @@ Cmdliner.Term.eval (Cli.lawspec_t driver, Cli.info)
|
7
src/lawspec/dune
Normal file
7
src/lawspec/dune
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
(include_subdirs unqualified)
|
||||||
|
|
||||||
|
(library
|
||||||
|
(public_name lawspec)
|
||||||
|
(libraries ANSITerminal sedlex menhirLib re cmdliner dune-build-info)
|
||||||
|
(preprocess (pps sedlex.ppx))
|
||||||
|
)
|
37
src/lawspec/literate/weawe.ml
Normal file
37
src/lawspec/literate/weawe.ml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
(*
|
||||||
|
This file is part of the Lawspec compiler, a specification language for tax and social benefits
|
||||||
|
computation rules.
|
||||||
|
Copyright (C) 2020 Inria, contributor: Denis Merigoux <denis.merigoux@inria.fr>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*)
|
||||||
|
|
||||||
|
(**
|
||||||
|
This modules weaves the source code and the legislative text together into a document
|
||||||
|
that law professionals can understand.
|
||||||
|
*)
|
||||||
|
|
||||||
|
module A = Ast
|
||||||
|
module P = Printf
|
||||||
|
|
||||||
|
let source_file_item_to_latex (i: A.source_file_item) : string =
|
||||||
|
match i with
|
||||||
|
| A.LawCode c -> P.sprintf "\\subsection{%s}" c
|
||||||
|
| A.LawText t -> t
|
||||||
|
| A.LawArticle a -> P.sprintf "\\paragraph{%s}" a
|
||||||
|
| A.CodeBlock -> "code"
|
||||||
|
|
||||||
|
let ast_to_latex (file : A.source_file) : string =
|
||||||
|
String.concat "\n\n" (List.map (fun i ->
|
||||||
|
source_file_item_to_latex i
|
||||||
|
) file )
|
@ -16,4 +16,10 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
type source_file = unit
|
type source_file_item =
|
||||||
|
| LawCode of string
|
||||||
|
| LawArticle of string
|
||||||
|
| LawText of string
|
||||||
|
| CodeBlock
|
||||||
|
|
||||||
|
type source_file = source_file_item list
|
@ -30,6 +30,7 @@ let rec lex_code lexbuf =
|
|||||||
| '\n' -> update lexbuf ; new_line lexbuf; lex_code lexbuf
|
| '\n' -> update lexbuf ; new_line lexbuf; lex_code lexbuf
|
||||||
| ' ' | '\t' -> update lexbuf; lex_code lexbuf
|
| ' ' | '\t' -> update lexbuf; lex_code lexbuf
|
||||||
| "*/" -> update lexbuf; is_code:= false; lex_law lexbuf
|
| "*/" -> update lexbuf; is_code:= false; lex_law lexbuf
|
||||||
|
| "code" -> update lexbuf; CODE
|
||||||
| any -> update lexbuf; lex_code lexbuf
|
| any -> update lexbuf; lex_code lexbuf
|
||||||
| _ -> raise_ParseError lexbuf
|
| _ -> raise_ParseError lexbuf
|
||||||
|
|
||||||
@ -39,6 +40,15 @@ and lex_law lexbuf =
|
|||||||
| '\n' -> update lexbuf ; new_line lexbuf; lex_law lexbuf
|
| '\n' -> update lexbuf ; new_line lexbuf; lex_law lexbuf
|
||||||
| "/*" -> update lexbuf; is_code := true; lex_code lexbuf
|
| "/*" -> update lexbuf; is_code := true; lex_code lexbuf
|
||||||
| eof -> update lexbuf ; EOF
|
| eof -> update lexbuf ; EOF
|
||||||
|
| "@@", Star white_space, Star (Compl '@'), Star white_space, "@@" ->
|
||||||
|
let extract_code_title =
|
||||||
|
R.regexp "@@\\s*([^#]*)\\s*@@"
|
||||||
|
in
|
||||||
|
let title = R.get_substring
|
||||||
|
(R.exec ~rex:extract_code_title (Sedlexing.Utf8.lexeme buf))
|
||||||
|
1
|
||||||
|
in
|
||||||
|
update lexbuf; LAW_CODE title
|
||||||
| "@", Star white_space, Star (Compl '@'), Star white_space, "@" ->
|
| "@", Star white_space, Star (Compl '@'), Star white_space, "@" ->
|
||||||
let extract_article_title =
|
let extract_article_title =
|
||||||
R.regexp "@\\s*([^#]*)\\s*@"
|
R.regexp "@\\s*([^#]*)\\s*@"
|
||||||
@ -47,8 +57,9 @@ and lex_law lexbuf =
|
|||||||
(R.exec ~rex:extract_article_title (Sedlexing.Utf8.lexeme buf))
|
(R.exec ~rex:extract_article_title (Sedlexing.Utf8.lexeme buf))
|
||||||
1
|
1
|
||||||
in
|
in
|
||||||
update lexbuf; ARTICLE title
|
update lexbuf; LAW_ARTICLE title
|
||||||
| any -> update lexbuf; lex_law lexbuf
|
| Plus (Compl ('@' | '/' | '\n')) ->
|
||||||
|
update lexbuf; LAW_TEXT (Sedlexing.Utf8.lexeme buf)
|
||||||
| _ -> raise_ParseError lexbuf
|
| _ -> raise_ParseError lexbuf
|
||||||
|
|
||||||
let lexer lexbuf =
|
let lexer lexbuf =
|
@ -17,12 +17,14 @@
|
|||||||
*)
|
*)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
open Ast
|
||||||
(** Module generated automaticcaly by Menhir, the parser generator *)
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%token EOF
|
%token EOF
|
||||||
%token<string> ARTICLE
|
%token<string> LAW_ARTICLE
|
||||||
|
%token<string> LAW_CODE
|
||||||
|
%token<string> LAW_TEXT
|
||||||
|
%token CODE
|
||||||
|
|
||||||
%type <Ast.source_file> source_file
|
%type <Ast.source_file> source_file
|
||||||
|
|
||||||
@ -31,8 +33,11 @@
|
|||||||
%%
|
%%
|
||||||
|
|
||||||
source_file_item:
|
source_file_item:
|
||||||
| title = ARTICLE { Cli.debug_print title }
|
| title = LAW_ARTICLE { LawArticle title }
|
||||||
|
| code = LAW_CODE { LawCode code }
|
||||||
|
| text = LAW_TEXT { LawText text }
|
||||||
|
| CODE { CodeBlock }
|
||||||
|
|
||||||
source_file:
|
source_file:
|
||||||
| source_file_item source_file { }
|
| i = source_file_item f = source_file { i::f }
|
||||||
| EOF { }
|
| EOF { [] }
|
49
src/main.ml
49
src/main.ml
@ -1,49 +1,2 @@
|
|||||||
(*
|
|
||||||
This file is part of the Lawspec compiler, a specification language for tax and social benefits
|
|
||||||
computation rules.
|
|
||||||
Copyright (C) 2019 Inria, contributor: Denis Merigoux <denis.merigoux@inria.fr>
|
|
||||||
|
|
||||||
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.
|
|
||||||
*)
|
|
||||||
|
|
||||||
open Cli
|
|
||||||
|
|
||||||
(** Entry function for the executable. Returns a negative number in case of error. *)
|
|
||||||
let main () : int =
|
|
||||||
parse_cli_args ();
|
|
||||||
Cli.debug_print "Reading files...";
|
|
||||||
let program = ref [] in
|
|
||||||
List.iter (fun source_file ->
|
|
||||||
let input = open_in source_file in
|
|
||||||
Cli.debug_print (Printf.sprintf "Parsing %s" source_file);
|
|
||||||
let lexbuf = Sedlex_menhir.create_lexbuf ~file:(Filename.basename source_file) (Sedlexing.Utf8.from_channel input) in
|
|
||||||
try
|
|
||||||
Parse_utils.current_file := source_file;
|
|
||||||
let commands = Sedlex_menhir.sedlex_with_menhir Lexer.lexer Parser.source_file lexbuf in
|
|
||||||
program := commands::!program;
|
|
||||||
close_in input
|
|
||||||
with
|
|
||||||
| Errors.LexingError msg | Errors.ParsingError msg ->
|
|
||||||
error_print msg
|
|
||||||
| Sedlex_menhir.ParseError msg -> begin
|
|
||||||
error_print
|
|
||||||
(Printf.sprintf "Parser error: %s" msg);
|
|
||||||
close_in input;
|
|
||||||
exit (-1)
|
|
||||||
end
|
|
||||||
) !source_files;
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
let _ =
|
let _ =
|
||||||
source_files := ["test/simple.lsp"];
|
Lawspec.Driver.main ()
|
||||||
main ()
|
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
|
@@ Code de la sécurité sociale @@
|
||||||
|
|
||||||
@ Article L521-3 @
|
@ Article L521-3 @
|
||||||
|
|
||||||
Blablabla
|
Blablabla, etc
|
||||||
|
|
||||||
|
dfl
|
||||||
|
|
||||||
|
1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
code keyword
|
code
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user