Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • theo.putegnat/infosec-ecomp
  • damien.armillon/infosec-ecomp
  • mouhamed.sougou/infosec-ecomp
  • cidre-public/compilation/infosec-ecomp
4 results
Show changes
Commits on Source (70)
tests/**/*.ast
tests/**/*.cfg
tests/**/*.cfg0
tests/**/*.cfg1
tests/**/*.cfg2
tests/**/*.e.dump
tests/**/*.e.html
tests/**/*.exe
tests/**/*.lex
tests/**/*.linear
tests/**/*.linear1
tests/**/*.ltl
tests/**/*.rtl
tests/**/*.s
tests/**/*.svg
tests/results.html
tests/__pycache__
src/_build
alpaga/_build
grammar.html
src/generated_parser.ml
src/config.ml
**/*.native
alpaga/ml_parser_generator
alpaga/alpaga
alpaga/ml_parser_generator.native
tykernel/*.ast
tykernel/*.cfg
tykernel/*.cfg0
tykernel/*.cfg1
tykernel/*.cfg2
tykernel/*.e.dump
tykernel/*.e.html
tykernel/*.exe
tykernel/*.lex
tykernel/*.linear
tykernel/*.linear1
tykernel/*.ltl
tykernel/*.rtl
tykernel/*.s
tykernel/*.svg
skeleton
sujet/_minted-tp
sujet/*.aux
sujet/*.fdb_latexmk
sujet/*.fls
sujet/*.log
sujet/*.out
sujet/*.pdf
sujet/*.synctex.gz
src/.vscode/
.vscode/
Makefile.config
\ No newline at end of file
all: main.native
all: ecomp
.PHONY: main.native
main.native:
include opts.mk
.PHONY: ecomp
src/config.ml: configure opts.mk
./configure ${CONF_OPTS}
.PHONY: alpaga
alpaga/alpaga:
make -C alpaga
src/generated_parser.ml: expr_grammar_action.g alpaga/alpaga
./alpaga/alpaga \
-g expr_grammar_action.g \
-pml src/generated_parser.ml \
-t grammar.html
./configure
make -C src
cp src/main.native main.native
ecomp: src/generated_parser.ml src/config.ml
make -C src
ln -sf src/_build/default/main.exe ecomp
clean:
make -C alpaga clean
rm -f src/generated_parser.ml
rm -f grammar.html
make -C src clean
rm -f main.native
rm -f ecomp
make -C tests clean
test: main.native
test: ecomp
make -C tests
No preview for this file type
ml_parser_generator
alpaga
ml_parser_generator.native
_build/
\ No newline at end of file
S .
B _build
PKG batteries
\ No newline at end of file
OCB=ocamlbuild -use-ocamlfind -cflag -g
#OCB=ocamlbuild -use-ocamlfind -cflag -g
SRC=ml_parser_generator.ml \
grammar_parser.ml \
......@@ -12,11 +12,9 @@ TG = alpaga
all: $(TG)
$(TG): ml_parser_generator.native
cp ml_parser_generator.native $(TG)
ml_parser_generator.native: $(SRC)
$(OCB) ml_parser_generator.native
$(TG): $(SRC)
dune build ml_parser_generator.exe
ln -sf _build/default/ml_parser_generator.exe alpaga
clean:
rm -f ml_parser_generator.native $(TG)
......
<.>: include
true: package(str, batteries)
true: use_menhir
(menhir
(modules grammar_parser_yacc)
)
(ocamllex grammar_lexer)
(executable
(name ml_parser_generator)
(libraries
batteries
menhirLib
)
(flags (:standard -warn-error -A -w -27 -w -33 -w -9 -w -39))
)
(lang dune 2.9)
(using menhir 2.1)
......@@ -11,7 +11,7 @@ type rule = { rule_nt: nonterm;
}
type grammar = { tokens: (tokent * string option) list;
nonterms: nonterm list;
nonterms: (nonterm * string option) list;
rules: rule list;
mlcode: string option;
axiom: nonterm option
......@@ -24,5 +24,6 @@ let dump_grammar oc (toks, nts, rules) =
Printf.fprintf oc "\nnon-terminals ";
List.iter (fun n -> Printf.fprintf oc " %s" n) nts;
Printf.fprintf oc "\nrules\n";
List.iter (fun (n,lt,a) -> Printf.fprintf oc "%s ->%s\n" n (print_seq (fun x -> x) lt)) rules
List.iter (fun (n,lt,_) ->
Printf.fprintf oc "%s ->%s\n" n (print_seq (fun x -> x) lt)) rules
{
open Grammar_parser_yacc
open Lexing
}
let digit = ['0'-'9']
......@@ -12,21 +13,27 @@ rule token = parse
| "/*" { comment_multiline lexbuf }
| '\n' { Lexing.new_line lexbuf; EOL }
| '{' { action 0 "" lexbuf }
| '<' { ttype "" lexbuf }
| "->" { ARROW }
| ">" { GT }
| "<" { LT }
| "axiom" { AXIOM }
| "tokens" { TOK }
| "non-terminals" { NT }
| "rules" { RULES }
| id as s { IDENTIFIER s }
| eof { EOF }
| _ as x { failwith (Printf.sprintf "unexpected char '%c'\n" x)}
| _ as x { let open Lexing in
failwith (Printf.sprintf "unexpected char '%c' at line %d col %d\n" x
(lexbuf.lex_curr_p.pos_lnum)
(lexbuf.lex_curr_p.pos_cnum - lexbuf.lex_curr_p.pos_bol))}
and action level s = parse
| '}' { if level = 0 then CODE s else action (level-1) (s ^ "}") lexbuf }
| '{' { action (level + 1) (s ^ "{") lexbuf }
| _ as x { if x == '\n' then Lexing.new_line lexbuf;
| _ as x { if x = '\n' then Lexing.new_line lexbuf;
action level (Printf.sprintf "%s%c" s x) lexbuf }
and ttype s = parse
| '>' { TTYPE s }
| _ as x { if x = '\n' then Lexing.new_line lexbuf;
ttype (Printf.sprintf "%s%c" s x) lexbuf }
and comment = parse
| '\n' { Lexing.new_line lexbuf; token lexbuf }
| _ { comment lexbuf }
......
......@@ -26,7 +26,7 @@ let parse_grammar file : grammar * nonterm =
List.fold_left
(fun (undef, used) prod ->
let undef =
if not (List.mem prod (List.map fst gram.tokens) || List.mem prod gram.nonterms || List.mem prod undef)
if not (List.mem_assoc prod gram.tokens || List.mem_assoc prod gram.nonterms || List.mem prod undef)
then prod::undef
else undef in
let used =
......@@ -46,7 +46,7 @@ let parse_grammar file : grammar * nonterm =
| Some axiom ->
(* Warn if some non terminals are never seen on the right hand side of a rule. *)
let unused_nts = List.filter (fun nt -> not (List.mem nt used_strings) && Some nt <> gram.axiom) gram.nonterms in
let unused_nts = List.filter (fun nt -> not (List.mem nt used_strings) && Some nt <> gram.axiom) (List.map fst gram.nonterms) in
if unused_nts <> [] then Printf.printf "The following non-terminals are declared but never appear on the right hand-side of a rule:\n%a\n" print_list unused_nts;
(* Warn if some tokens are never seen on the right hand side of a rule. *)
......@@ -59,5 +59,5 @@ let parse_grammar file : grammar * nonterm =
match Hashtbl.find_opt h r.rule_nt with
| None -> Hashtbl.add h r.rule_nt [r]
| Some lp -> Hashtbl.replace h r.rule_nt (lp@[r]) ) (gram.rules);
let rules = List.concat (List.map (fun n -> hashget_def h n []) gram.nonterms) in
let rules = List.concat (List.map (fun n -> hashget_def h n []) (List.map fst gram.nonterms)) in
{ gram with rules = rules }, axiom
......@@ -4,9 +4,10 @@
%}
%token EOF EOL TOK NT RULES ARROW AXIOM LT GT
%token EOF EOL TOK NT RULES ARROW AXIOM //LT GT
%token<string> IDENTIFIER
%token<string> CODE
%token<string> TTYPE
%start main
%type <Grammar.grammar> main
......@@ -16,7 +17,7 @@
main:
| AXIOM IDENTIFIER EOL main { let r = $4 in {r with axiom = Some $2 }}
| TOK list_tokens EOL main { let r = $4 in {r with tokens = r.tokens @ $2} }
| NT list_ident EOL main { let r = $4 in {r with nonterms = r.nonterms @ $2} }
| NT list_nts EOL main { let r = $4 in {r with nonterms = r.nonterms @ $2} }
| CODE main { let r = $2 in { r with mlcode = Some ($1) }}
| RULES EOL rules EOF { { tokens = []; nonterms = []; axiom = None;
rules = $3; mlcode = None } }
......@@ -24,7 +25,7 @@
;
typed_tokens:
| IDENTIFIER LT IDENTIFIER GT { ($1, Some $3) }
| IDENTIFIER TTYPE { ($1, Some $2) }
| IDENTIFIER { ($1, None)}
;
......@@ -35,6 +36,20 @@
;
typed_nts:
| IDENTIFIER TTYPE { ($1, Some $2) }
| IDENTIFIER { ($1, None)}
;
list_nts:
| typed_nts list_nts { $1 :: $2}
| { [] }
;
list_ident:
| IDENTIFIER list_ident { $1 :: $2}
| { [] }
......
......@@ -72,7 +72,8 @@ let follow_nt (toks,nts,rules) (n: string) : bool =
then follow (fst x)
else Set.empty) (first_prod (toks,nts,rules) (snd x))) l in
let l = List.fold_left Set.union Set.empty l in
Hashtbl.add followt n l; old <> l
Hashtbl.add followt n l;
not (Set.equal old l)
let follow_all_nt (toks,nts,rules) () = apply_on_all (follow_nt (toks,nts,rules)) nts
......@@ -100,6 +101,17 @@ let string_of_lltype = function
| Follow i -> Printf.sprintf "<a style='color:red;' href=\"#rule-%d\">%d</a>" i i
let check_conflicts (toks,nts,rules) () =
List.fold_left
(fun acc x ->
List.fold_left (fun acc t ->
let rs = (hashget_def lltable (x,t) []) in
if List.length rs > 1 then true else acc
) acc toks
) false
nts
let print_table (toks,nts,rules) oc () =
Format.fprintf oc "<!DOCTYPE html>" ;
Format.fprintf oc "<html><head><link rel='stylesheet' type='text/css' href='style.css'/></head>\n";
......
......@@ -25,8 +25,11 @@ let default_action (pl: string list) : string =
let resolve_vars s =
Str.global_replace (Str.regexp "\\$\\([0-9]+\\)") "p\\1" s
let make_nt (table: string*string -> lltype list) (toks,nts,rules) oc n () =
Printf.fprintf oc "and parse_%s tokens () =\n" n;
let make_nt (table: string*string -> lltype list) (toks,nts,rules) oc (n,ot) () =
let t = match ot with | None -> "_" | Some t -> t in
let type_annot = Printf.sprintf ": ((%s) * ((token*Lexing.position option) list)) res" t
in
Printf.fprintf oc "and parse_%s (tokens: ((token*Lexing.position option) list)) () %s=\n" n type_annot;
Printf.fprintf oc " begin match tokens with\n";
List.iteri
(fun i t ->
......@@ -41,47 +44,37 @@ let make_nt (table: string*string -> lltype list) (toks,nts,rules) oc n () =
then Printf.fprintf oc " eat_%s tokens >>= fun (p%d, tokens) ->\n" t (i + 1)
else Printf.fprintf oc " parse_%s tokens () >>= fun (p%d, tokens) ->\n" t (i+1))
pl;
Printf.fprintf oc "\n" ;
Printf.fprintf oc " let res =\n" ;
(match act with
| Some act -> Printf.fprintf oc " %s\n" (resolve_vars act)
| _ ->
Printf.fprintf oc " %s\n" (resolve_vars (default_action pl))
);
Printf.fprintf oc " in OK (res, tokens)\n" ;
Printf.fprintf oc "end\n";
let act = match act with Some act -> act | _ -> default_action pl in
Printf.fprintf oc " let res = %s in\n" (resolve_vars act);
Printf.fprintf oc " OK (res, tokens)\n" ;
Printf.fprintf oc " end\n";
)
toks;
let expected = List.filter (fun t -> List.length (table (n,t)) > 0) toks in
Printf.fprintf oc " | tokens -> \n";
Printf.fprintf oc " let got,lexpos = match tokens with [] -> \"EOF\",None | (symbol, lexpos) :: _ -> (string_of_symbol symbol, lexpos) in Error (\n";
Printf.fprintf oc " (match lexpos with \n";
Printf.fprintf oc " | Some lexpos -> Printf.sprintf \"At %%s, error while parsing %s\\n\" (string_of_position lexpos) \n" n;
Printf.fprintf oc " | tokens ->\n";
Printf.fprintf oc " let got,lexpos =\n match tokens with\n [] -> \"EOF\",None\n | (symbol, lexpos) :: _ -> (string_of_symbol symbol, lexpos)\n in Error (\n";
Printf.fprintf oc " (match lexpos with\n";
Printf.fprintf oc " | Some lexpos -> Printf.sprintf \"At %%s, error while parsing %s\\n\" (string_of_position lexpos)\n" n;
Printf.fprintf oc " | None -> Printf.sprintf \"Error while parsing %s\\n\" )^\n" n;
Printf.fprintf oc " Printf.sprintf \"Expected one of \"^\n";
begin
match expected with
[] -> Printf.fprintf oc "Printf.sprintf \"{}\" ^\n"
| a::r ->
List.iteri (fun i t ->
Printf.fprintf oc "Printf.sprintf \"%s %%s\" (string_of_symbol default_%s)^\n" (if i = 0 then "{" else ",") t;
) (a::r);
Printf.fprintf oc "Printf.sprintf \"}\" ^ \n"
end;
Printf.fprintf oc " Printf.sprintf \" but got '%%s' instead.\\n\" got\n";
Printf.fprintf oc " Printf.sprintf \"Expected one of {%%s}\"\n";
Printf.fprintf oc " (String.concat \", \" (List.map string_of_symbol [%s])) ^\n"
(String.concat ";" (List.map (fun s -> "default_"^s) expected)) ;
Printf.fprintf oc " Printf.sprintf \" but got '%%s' instead.\\n\" got\n ^ ";
Printf.fprintf oc " Printf.sprintf \" '%%s' \\n\" (String.concat \",\" (List.map (fun (x, _) -> string_of_symbol x) (List.take 10 tokens)))\n";
Printf.fprintf oc " )";
Printf.fprintf oc "\n end\n\n"
let make_parser (table: string*string -> lltype list)
(toks,nts,rules,mlcode)
(typ: (tokent * string) list)
(nttyp: (nonterm * string) list)
oc () =
Stdlib.Option.iter (fun mlcode -> Printf.fprintf oc "\n\n%s\n\n" mlcode) mlcode;
List.iter (fun t ->
begin match List.assoc_opt t typ with
| Some ty ->
begin
Printf.fprintf oc "let is_%s = function \n" t;
Printf.fprintf oc "let is_%s = function\n" t;
Printf.fprintf oc " | %s _ -> true\n" t;
Printf.fprintf oc " | _ -> false\n";
......@@ -90,11 +83,12 @@ let make_parser (table: string*string -> lltype list)
"string" -> "\"\""
| "int" -> "0"
| "bool" -> "false"
| "char" -> "'a'"
| _ -> failwith (Printf.sprintf "Don't know how to generate a default value of type %s" ty)
)
end
| None -> begin
Printf.fprintf oc "let is_%s = function \n" t;
Printf.fprintf oc "let is_%s = function\n" t;
Printf.fprintf oc " | %s -> true\n" t;
Printf.fprintf oc " | _ -> false\n";
Printf.fprintf oc "let default_%s = %s\n" t t
......@@ -102,23 +96,23 @@ let make_parser (table: string*string -> lltype list)
end;
) toks;
List.iter (fun t ->
Printf.fprintf oc "let eat_%s = function \n" t;
Printf.fprintf oc "let eat_%s = function\n" t;
begin match List.assoc_opt t typ with
| Some _ -> Printf.fprintf oc "| (%s(x),_) :: rtokens -> OK (x, rtokens)\n" t
| None -> Printf.fprintf oc "| (%s,_) :: rtokens -> OK ((), rtokens)\n" t
end;
Printf.fprintf oc "| (x,Some pos) :: _ -> Error (Printf.sprintf \"At position %%s, expected %%s, got %%s.\\n\"";
Printf.fprintf oc " (string_of_position pos)";
Printf.fprintf oc " (string_of_symbol default_%s)" t;
Printf.fprintf oc " (string_of_symbol x))";
Printf.fprintf oc " | (x,None) :: _ -> Error (Printf.sprintf \"Expected %%s, got %%s.\\n\"";
Printf.fprintf oc " (string_of_symbol default_%s)" t;
Printf.fprintf oc " (string_of_symbol x))";
Printf.fprintf oc "| (x,Some pos) :: _ -> Error (Printf.sprintf \"At position %%s, expected %%s, got %%s.\\n\"\n";
Printf.fprintf oc " (string_of_position pos)\n";
Printf.fprintf oc " (string_of_symbol default_%s)\n" t;
Printf.fprintf oc " (string_of_symbol x))\n";
Printf.fprintf oc " | (x,None) :: _ -> Error (Printf.sprintf \"Expected %%s, got %%s.\\n\"\n";
Printf.fprintf oc " (string_of_symbol default_%s)\n" t;
Printf.fprintf oc " (string_of_symbol x))\n";
Printf.fprintf oc " | _ -> Error (Printf.sprintf \"Expected %%s, got EOF.\\n\" (string_of_symbol default_%s))\n" t;
) toks;
Printf.fprintf oc "let rec ____unused = () \n";
List.iter (fun n -> make_nt table (toks,nts,rules) oc n ()) nts
Printf.fprintf oc "let rec ____unused = ()\n";
List.iter (fun n -> make_nt table (toks,nts,rules) oc (n, List.assoc_opt n nttyp) ()) nts
let nts_ordered start (toks,nts,rules) =
let nts =
......@@ -164,6 +158,9 @@ let _ =
iter_first (toks, nts, rules) ();
iter_follownt (toks, nts, rules) ();
fill_lltable (toks, nts, rules) ();
let has_conflict = check_conflicts (toks, nts, rules) () in
if has_conflict
then Printf.fprintf stderr "Warning! There is a conflict in your grammar. Check the prediction table for more details.\n";
(match !table_file with
| Some tfile -> let oc = open_out tfile in
print_html (toks, nts, rules) (Format.formatter_of_out_channel oc) ();
......@@ -180,6 +177,11 @@ let _ =
| None -> None
| Some typ -> Some (t,typ)
) gram.tokens)
(List.filter_map (fun (t,o) ->
match o with
| None -> None
| Some typ -> Some (t,typ)
) gram.nonterms)
oc ();
close_out oc
)
#!/bin/bash
LEX_HAND="true"
ALPAGA_PARSER="true"
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-l|--lex-hand)
LEX_HAND="true"
shift
;;
-L|--lex-ocamllex)
LEX_HAND="false"
shift
;;
-a|--alpaga-parser)
ALPAGA_PARSER="true"
shift
;;
-m|--menhir-parser)
ALPAGA_PARSER="false"
shift
;;
*) # unknown option
shift # past argument
;;
esac
done
RUNTIME=$(pwd)/runtime
RVAS=$(which -a riscv64-unknown-linux-gnu-as riscv64-unknown-elf-as riscv64-linux-gnu-as 2>/dev/null | grep -v "not found" | head -n1)
RVLD=$(which -a riscv64-unknown-linux-gnu-ld riscv64-unknown-elf-ld riscv64-linux-gnu-ld 2>/dev/null | grep -v "not found" | head -n1)
QEMU32=$(which -a qemu-riscv32 qemu-riscv32-static 2>/dev/null | grep -v "not found" | head -n1)
QEMU64=$(which -a qemu-riscv64 qemu-riscv64-static 2>/dev/null | grep -v "not found" | head -n1)
echo "let runtime_dir = \"${RUNTIME}\"" > src/config.ml
echo "let qemu_path = \"/usr/local/bin/qemu-riscv\"" >> src/config.ml
echo "let qemu32 = \"${QEMU32}\"" >> src/config.ml
echo "let qemu64 = \"${QEMU64}\"" >> src/config.ml
echo "let rv_as = \"${RVAS}\"" >> src/config.ml
echo "let rv_ld = \"${RVLD}\"" >> src/config.ml
echo "let os_target = \"linux\"" >> src/config.ml
echo "let lex_hand = $LEX_HAND" >> src/config.ml
echo "let alpaga_parser = $ALPAGA_PARSER" >> src/config.ml
......@@ -2,7 +2,7 @@ tokens SYM_EOF SYM_IDENTIFIER<string> SYM_INTEGER<int> SYM_PLUS SYM_MINUS SYM_AS
tokens SYM_LPARENTHESIS SYM_RPARENTHESIS SYM_LBRACE SYM_RBRACE
tokens SYM_ASSIGN SYM_SEMICOLON SYM_RETURN SYM_IF SYM_WHILE SYM_ELSE SYM_COMMA SYM_PRINT
tokens SYM_EQUALITY SYM_NOTEQ SYM_LT SYM_LEQ SYM_GT SYM_GEQ
non-terminals S INSTR INSTRS LINSTRS ELSE EXPR FACTOR
non-terminals S INSTR<tree> INSTRS<tree list> LINSTRS ELSE EXPR FACTOR
non-terminals LPARAMS REST_PARAMS
non-terminals IDENTIFIER INTEGER
non-terminals FUNDEF FUNDEFS
......
......@@ -44,7 +44,7 @@
<div id="memstate"></div>
</div>
<div id="expr">
<input type="text" id="expr_input" size="30" /><br>
<input type="text" id="expr_input" size="20" /><br>
Result: <span id="expr_res"></span><hr>
<div id="subexprs"></div>
</div>
......
......@@ -678,10 +678,10 @@ function handle_command(d){
for(let [evar,loc] of Object.entries(fb['vars'])){
if(Object.keys(loc).includes("reg")){
p.insert("span").html("Var "+evar+": "+loc["reg"])
p.insert("span").html("Var "+evar+": Reg "+loc["reg"])
.insert("br");
} else {
p.insert("span").html("Var "+evar+": "+loc["stk"])
p.insert("span").html("Var "+evar+": Stk "+loc["stk"])
.insert("br");
}
}
......
......@@ -54,7 +54,7 @@ html {
}
#body{
display: grid;
grid-template-columns: [ctrl] 300px [code] 250px [outcfg] 600px [state] 700px;
grid-template-columns: [ctrl] 250px [code] 400px [outcfg] 500px [state] 700px;
grid-template-rows: [row1] 200px [row2] 200px [row3] 400px [row4];
}
#code {
......