From 091e4a356a31c64e0f1e943e20badb5613f1b21f Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 30 Dec 2019 21:37:22 +0000 Subject: [PATCH] Implement -include (optional include) command. --- src/lexer.mll | 1 + src/parser.mly | 55 +++++++++++++++++++++++++++++++------------------------ 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/lexer.mll b/src/lexer.mll index 617c10f..84f2af2 100644 --- a/src/lexer.mll +++ b/src/lexer.mll @@ -54,6 +54,7 @@ rule read = | "tactic" { TACTIC_KEYWORD } | "let" { LET } | "include" { INCLUDE } + | "-include" { OPTINCLUDE } | "*" id { (* NB: The initial '*' is part of the name. *) TACTIC (Lexing.lexeme lexbuf) } | id { ID (Lexing.lexeme lexbuf) } diff --git a/src/parser.mly b/src/parser.mly index c6f961d..e45e90b 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -26,6 +26,33 @@ open Printf * by include files. *) let lexer_read = ref None + +let find_on_include_path filename = + if not (Filename.is_implicit filename) then filename + else ( + let rec loop = function + | [] -> filename + | inc :: incs -> + let path = inc // filename in + if Sys.file_exists path then path else loop incs + in + loop Cmdline.includes + ) + +let do_include env loc filename optflag file = + let filename = Ast.substitute env loc filename in + let filename = find_on_include_path filename in + if optflag && not (Sys.file_exists filename) then env + else ( + let fp = open_in filename in + let lexbuf = Lexing.from_channel fp in + lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = filename }; + let reader = + match !lexer_read with None -> assert false | Some r -> r in + let env' = file reader lexbuf in + close_in fp; + Ast.Env.merge env env' + ) %} (* Tokens. *) @@ -40,6 +67,7 @@ let lexer_read = ref None %token LEFT_ARRAY %token LEFT_PAREN %token LET +%token OPTINCLUDE %token RIGHT_ARRAY %token RIGHT_PAREN %token STRING @@ -58,30 +86,9 @@ file: stmts: | (* none *) { Ast.Env.empty } | stmts INCLUDE STRING - { - let env = $1 in - let filename = Ast.substitute env $loc $3 in - let rec find_on_include_path = - function - | [] -> filename - | inc :: incs -> - let path = inc // filename in - if Sys.file_exists path then path - else find_on_include_path incs - in - let filename = - if Filename.is_implicit filename then - find_on_include_path Cmdline.includes - else filename in - let fp = open_in filename in - let lexbuf = Lexing.from_channel fp in - lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = filename }; - let reader = - match !lexer_read with None -> assert false | Some r -> r in - let env' = file reader lexbuf in - close_in fp; - Ast.Env.merge env env' - } + { do_include $1 $loc $3 false file } + | stmts OPTINCLUDE STRING + { do_include $1 $loc $3 true file } | stmts stmt { let name, expr = $2 in Ast.Env.add name expr $1 } ; -- 1.8.3.1