mirror of
https://github.com/CatalaLang/catala.git
synced 2024-09-19 16:28:12 +03:00
Improved architecture
This commit is contained in:
parent
12cee7627b
commit
56bc45db9d
@ -1,6 +1,6 @@
|
||||
(lang dune 1.10)
|
||||
(name lawspec)
|
||||
(version 1.0.2)
|
||||
(version 0.1)
|
||||
(generate_opam_files true)
|
||||
|
||||
(source (uri git+https://gitlab.inria.fr/verifisc/lawspec.git))
|
||||
@ -22,6 +22,7 @@
|
||||
(ANSITerminal (>= 0.8.2))
|
||||
(sedlex (>= 2.1))
|
||||
(menhirLib (>= 20200211))
|
||||
(dune-build-info (>= 2.0.1))
|
||||
(dune (and :build ))
|
||||
)
|
||||
)
|
||||
|
@ -11,7 +11,7 @@ authors: ["Denis Merigoux"]
|
||||
bug-reports: "https://gitlab.inria.fr/verifisc/lawspec/issues"
|
||||
homepage: "https://gitlab.inria.fr/verifisc/lawspec"
|
||||
license: "Apache2"
|
||||
version: "1.0.2"
|
||||
version: "0.1"
|
||||
dev-repo: "git+https://gitlab.inria.fr/verifisc/lawspec.git"
|
||||
synopsis: "Low-level language for tax code specification"
|
||||
description: """
|
||||
@ -23,5 +23,6 @@ depends: [
|
||||
"ANSITerminal" {>= "0.8.2"}
|
||||
"sedlex" {>= "2.1"}
|
||||
"menhirLib" {>= "20200211"}
|
||||
"dune-build-info" {>= "2.0.1"}
|
||||
"dune" {build}
|
||||
]
|
||||
|
13
src/dune
13
src/dune
@ -1,9 +1,6 @@
|
||||
(include_subdirs unqualified)
|
||||
|
||||
(executable
|
||||
(name main)
|
||||
(public_name lawspec)
|
||||
(package lawspec)
|
||||
(libraries ANSITerminal sedlex menhirLib re)
|
||||
(preprocess (pps sedlex.ppx))
|
||||
)
|
||||
(name main)
|
||||
(package lawspec)
|
||||
(public_name lawspec)
|
||||
(libraries lawspec)
|
||||
(preprocess (pps sedlex.ppx)))
|
||||
|
@ -22,19 +22,67 @@ let source_files : string list ref = ref []
|
||||
(** Prints debug information *)
|
||||
let debug_flag = ref false
|
||||
|
||||
let parse_cli_args () =
|
||||
(* 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
|
||||
open Cmdliner
|
||||
|
||||
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 }*)
|
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.
|
||||
*)
|
||||
|
||||
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
|
||||
| ' ' | '\t' -> update lexbuf; lex_code lexbuf
|
||||
| "*/" -> update lexbuf; is_code:= false; lex_law lexbuf
|
||||
| "code" -> update lexbuf; CODE
|
||||
| any -> update lexbuf; lex_code lexbuf
|
||||
| _ -> raise_ParseError lexbuf
|
||||
|
||||
@ -39,6 +40,15 @@ and lex_law lexbuf =
|
||||
| '\n' -> update lexbuf ; new_line lexbuf; lex_law lexbuf
|
||||
| "/*" -> update lexbuf; is_code := true; lex_code lexbuf
|
||||
| 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, "@" ->
|
||||
let extract_article_title =
|
||||
R.regexp "@\\s*([^#]*)\\s*@"
|
||||
@ -47,8 +57,9 @@ and lex_law lexbuf =
|
||||
(R.exec ~rex:extract_article_title (Sedlexing.Utf8.lexeme buf))
|
||||
1
|
||||
in
|
||||
update lexbuf; ARTICLE title
|
||||
| any -> update lexbuf; lex_law lexbuf
|
||||
update lexbuf; LAW_ARTICLE title
|
||||
| Plus (Compl ('@' | '/' | '\n')) ->
|
||||
update lexbuf; LAW_TEXT (Sedlexing.Utf8.lexeme buf)
|
||||
| _ -> raise_ParseError lexbuf
|
||||
|
||||
let lexer lexbuf =
|
@ -17,12 +17,14 @@
|
||||
*)
|
||||
|
||||
%{
|
||||
|
||||
(** Module generated automaticcaly by Menhir, the parser generator *)
|
||||
open Ast
|
||||
%}
|
||||
|
||||
%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
|
||||
|
||||
@ -31,8 +33,11 @@
|
||||
%%
|
||||
|
||||
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_item source_file { }
|
||||
| EOF { }
|
||||
| i = source_file_item f = source_file { i::f }
|
||||
| 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 _ =
|
||||
source_files := ["test/simple.lsp"];
|
||||
main ()
|
||||
Lawspec.Driver.main ()
|
||||
|
@ -1,10 +1,16 @@
|
||||
@@ Code de la sécurité sociale @@
|
||||
|
||||
@ Article L521-3 @
|
||||
|
||||
Blablabla
|
||||
Blablabla, etc
|
||||
|
||||
dfl
|
||||
|
||||
1)
|
||||
|
||||
/*
|
||||
|
||||
code keyword
|
||||
code
|
||||
|
||||
*/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user