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 (80)
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 src/_build
parser_generator/_build
grammar.html grammar.html
src/generated_parser.ml src/generated_parser.ml
src/config.ml
**/*.native **/*.native
parser_generator/ml_parser_generator
parser_generator/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 skeleton
sujet/_minted-tp src/.vscode/
sujet/*.aux .vscode/
sujet/*.fdb_latexmk Makefile.config
sujet/*.fls \ No newline at end of file
sujet/*.log
sujet/*.out
sujet/*.pdf
sujet/*.synctex.gz
all: main.native all: ecomp
.PHONY: main.native include opts.mk
main.native:
.PHONY: ecomp
src/config.ml: configure opts.mk
./configure ${CONF_OPTS}
.PHONY: alpaga
alpaga/alpaga:
make -C alpaga make -C alpaga
src/generated_parser.ml: expr_grammar_action.g alpaga/alpaga
./alpaga/alpaga \ ./alpaga/alpaga \
-g expr_grammar_action.g \ -g expr_grammar_action.g \
-pml src/generated_parser.ml \ -pml src/generated_parser.ml \
-t grammar.html -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: clean:
make -C alpaga clean make -C alpaga clean
rm -f src/generated_parser.ml rm -f src/generated_parser.ml
rm -f grammar.html rm -f grammar.html
make -C src clean make -C src clean
rm -f main.native rm -f ecomp
make -C tests clean make -C tests clean
test: main.native test: ecomp
make -C tests 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 \ SRC=ml_parser_generator.ml \
grammar_parser.ml \ grammar_parser.ml \
...@@ -12,11 +12,9 @@ TG = alpaga ...@@ -12,11 +12,9 @@ TG = alpaga
all: $(TG) all: $(TG)
$(TG): ml_parser_generator.native $(TG): $(SRC)
cp ml_parser_generator.native $(TG) dune build ml_parser_generator.exe
ln -sf _build/default/ml_parser_generator.exe alpaga
ml_parser_generator.native: $(SRC)
$(OCB) ml_parser_generator.native
clean: clean:
rm -f ml_parser_generator.native $(TG) rm -f ml_parser_generator.native $(TG)
......
...@@ -82,13 +82,13 @@ arbre de syntaxe abstraite. Pour ce faire, vous avez deux choses à faire : ...@@ -82,13 +82,13 @@ arbre de syntaxe abstraite. Pour ce faire, vous avez deux choses à faire :
accolades, qui sera copié au début du code source généré pour l'analyseur accolades, qui sera copié au début du code source généré pour l'analyseur
syntaxique. (en fait dans le squelette qui vous est fourni, ce bloc de code syntaxique. (en fait dans le squelette qui vous est fourni, ce bloc de code
est déjà présent, et vous n'avez qu'à le remplir.) est déjà présent, et vous n'avez qu'à le remplir.)
- après chaque règle 'X -> w1 w2 ... wn', ajoutez du code entre accolades qui - après chaque règle 'X -> w1 w2 ... wn', ajoutez du code entre accolades qui
construit le sous-arbre correspondant à la dérivation effectuée par cette construit le sous-arbre correspondant à la dérivation effectuée par cette
règle. On appelle ce code une **action**. règle. On appelle ce code une **action**.
Le code que vous écrivez correspond donc à la construction d'un terme OCaml. Le code que vous écrivez correspond donc à la construction d'un terme OCaml.
Par exemple, le morceau suivant vous est fourni : Par exemple, le morceau suivant vous est fourni :
''' '''
S -> GLOBDEF SYM_EOF { Node (Tlistglobdef, [$1]) } S -> GLOBDEF SYM_EOF { Node (Tlistglobdef, [$1]) }
...@@ -100,22 +100,22 @@ arbre de syntaxe abstraite. Pour ce faire, vous avez deux choses à faire : ...@@ -100,22 +100,22 @@ arbre de syntaxe abstraite. Pour ce faire, vous avez deux choses à faire :
Node (Tfundef, [$1; Node (Tfunargs, fargs) ; instr ]) Node (Tfundef, [$1; Node (Tfunargs, fargs) ; instr ])
} }
''' '''
Pour une règle X -> w1 w2 ... wn, les variables $i correspondent aux actions Pour une règle X -> w1 w2 ... wn, les variables $i correspondent aux actions
générées par le symbole wi. Par exemple, dans l'action de la première règle, générées par le symbole wi. Par exemple, dans l'action de la première règle,
la variable $1 correspond à l'arbre rendu par le non-terminal GLOBDEF. la variable $1 correspond à l'arbre rendu par le non-terminal GLOBDEF.
Les définitions des arbres et nœuds sont trouvées dans le fichier src/ast.ml. Les définitions des arbres et nœuds sont trouvées dans le fichier src/ast.ml.
Ces actions vont servir à générer le parser, ce qui se fera avec la commande : Ces actions vont servir à générer le parser, ce qui se fera avec la commande :
''' '''
./ml_parser_generator -g <votre_fichier_de_grammaire.g> -t <table.html> -pml <generated_parser.ml> ./ml_parser_generator -g <votre_fichier_de_grammaire.g> -t <table.html> -pml <generated_parser.ml>
''' '''
ce qui créera le fichier <generated_parser.ml> à l'endroit où vous l'avez Cela créera le fichier <generated_parser.ml> à l'endroit où vous l'avez
indiqué. indiqué.
En fait, les différents Makefile de ce projet font que vous n'aurez En fait, les différents Makefile de ce projet font que vous n'aurez
normalement pas à écrire cette commande à la main : un simple 'make test' à la normalement pas à écrire cette commande à la main : un simple 'make test' à la
racine de ce projet devrait faire tout ce dont vous avez besoin. racine de ce projet devrait faire tout ce dont vous avez besoin.
<.>: 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; ...@@ -11,7 +11,7 @@ type rule = { rule_nt: nonterm;
} }
type grammar = { tokens: (tokent * string option) list; type grammar = { tokens: (tokent * string option) list;
nonterms: nonterm list; nonterms: (nonterm * string option) list;
rules: rule list; rules: rule list;
mlcode: string option; mlcode: string option;
axiom: nonterm option axiom: nonterm option
...@@ -24,5 +24,6 @@ let dump_grammar oc (toks, nts, rules) = ...@@ -24,5 +24,6 @@ let dump_grammar oc (toks, nts, rules) =
Printf.fprintf oc "\nnon-terminals "; Printf.fprintf oc "\nnon-terminals ";
List.iter (fun n -> Printf.fprintf oc " %s" n) nts; List.iter (fun n -> Printf.fprintf oc " %s" n) nts;
Printf.fprintf oc "\nrules\n"; 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 Grammar_parser_yacc
open Lexing
} }
let digit = ['0'-'9'] let digit = ['0'-'9']
...@@ -9,23 +10,34 @@ let id = letter (digit|letter|'_')* ...@@ -9,23 +10,34 @@ let id = letter (digit|letter|'_')*
rule token = parse rule token = parse
| [' ' '\t'] { token lexbuf } | [' ' '\t'] { token lexbuf }
| "//" { comment lexbuf } | "//" { comment lexbuf }
| "/*" { comment_multiline lexbuf }
| '\n' { Lexing.new_line lexbuf; EOL } | '\n' { Lexing.new_line lexbuf; EOL }
| '{' { action 0 "" lexbuf } | '{' { action 0 "" lexbuf }
| '<' { ttype "" lexbuf }
| "->" { ARROW } | "->" { ARROW }
| ">" { GT }
| "<" { LT }
| "axiom" { AXIOM } | "axiom" { AXIOM }
| "tokens" { TOK } | "tokens" { TOK }
| "non-terminals" { NT } | "non-terminals" { NT }
| "rules" { RULES } | "rules" { RULES }
| id as s { IDENTIFIER s } | id as s { IDENTIFIER s }
| eof { EOF } | 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 and action level s = parse
| '}' { if level = 0 then CODE s else action (level-1) (s ^ "}") lexbuf } | '}' { if level = 0 then CODE s else action (level-1) (s ^ "}") lexbuf }
| '{' { 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 } 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 and comment = parse
| '\n' { Lexing.new_line lexbuf; token lexbuf } | '\n' { Lexing.new_line lexbuf; token lexbuf }
| _ { comment lexbuf } | _ { comment lexbuf }
and comment_multiline = parse
| '\n' { Lexing.new_line lexbuf; comment_multiline lexbuf }
| "*/" { token lexbuf }
| _ { comment_multiline lexbuf }
...@@ -26,7 +26,7 @@ let parse_grammar file : grammar * nonterm = ...@@ -26,7 +26,7 @@ let parse_grammar file : grammar * nonterm =
List.fold_left List.fold_left
(fun (undef, used) prod -> (fun (undef, used) prod ->
let undef = 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 then prod::undef
else undef in else undef in
let used = let used =
...@@ -46,7 +46,7 @@ let parse_grammar file : grammar * nonterm = ...@@ -46,7 +46,7 @@ let parse_grammar file : grammar * nonterm =
| Some axiom -> | Some axiom ->
(* Warn if some non terminals are never seen on the right hand side of a rule. *) (* 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; 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. *) (* 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 = ...@@ -59,5 +59,5 @@ let parse_grammar file : grammar * nonterm =
match Hashtbl.find_opt h r.rule_nt with match Hashtbl.find_opt h r.rule_nt with
| None -> Hashtbl.add h r.rule_nt [r] | None -> Hashtbl.add h r.rule_nt [r]
| Some lp -> Hashtbl.replace h r.rule_nt (lp@[r]) ) (gram.rules); | 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 { gram with rules = rules }, axiom
...@@ -4,9 +4,10 @@ ...@@ -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> IDENTIFIER
%token<string> CODE %token<string> CODE
%token<string> TTYPE
%start main %start main
%type <Grammar.grammar> main %type <Grammar.grammar> main
...@@ -16,7 +17,7 @@ ...@@ -16,7 +17,7 @@
main: main:
| AXIOM IDENTIFIER EOL main { let r = $4 in {r with axiom = Some $2 }} | 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} } | 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) }} | CODE main { let r = $2 in { r with mlcode = Some ($1) }}
| RULES EOL rules EOF { { tokens = []; nonterms = []; axiom = None; | RULES EOL rules EOF { { tokens = []; nonterms = []; axiom = None;
rules = $3; mlcode = None } } rules = $3; mlcode = None } }
...@@ -24,7 +25,7 @@ ...@@ -24,7 +25,7 @@
; ;
typed_tokens: typed_tokens:
| IDENTIFIER LT IDENTIFIER GT { ($1, Some $3) } | IDENTIFIER TTYPE { ($1, Some $2) }
| IDENTIFIER { ($1, None)} | IDENTIFIER { ($1, None)}
; ;
...@@ -35,6 +36,20 @@ ...@@ -35,6 +36,20 @@
; ;
typed_nts:
| IDENTIFIER TTYPE { ($1, Some $2) }
| IDENTIFIER { ($1, None)}
;
list_nts:
| typed_nts list_nts { $1 :: $2}
| { [] }
;
list_ident: list_ident:
| IDENTIFIER list_ident { $1 :: $2} | IDENTIFIER list_ident { $1 :: $2}
| { [] } | { [] }
......
...@@ -72,7 +72,8 @@ let follow_nt (toks,nts,rules) (n: string) : bool = ...@@ -72,7 +72,8 @@ let follow_nt (toks,nts,rules) (n: string) : bool =
then follow (fst x) then follow (fst x)
else Set.empty) (first_prod (toks,nts,rules) (snd x))) l in else Set.empty) (first_prod (toks,nts,rules) (snd x))) l in
let l = List.fold_left Set.union Set.empty 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 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 ...@@ -100,6 +101,17 @@ let string_of_lltype = function
| Follow i -> Printf.sprintf "<a style='color:red;' href=\"#rule-%d\">%d</a>" i i | 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 () = let print_table (toks,nts,rules) oc () =
Format.fprintf oc "<!DOCTYPE html>" ; Format.fprintf oc "<!DOCTYPE html>" ;
Format.fprintf oc "<html><head><link rel='stylesheet' type='text/css' href='style.css'/></head>\n"; Format.fprintf oc "<html><head><link rel='stylesheet' type='text/css' href='style.css'/></head>\n";
......
...@@ -19,13 +19,17 @@ let rec make_list l = ...@@ -19,13 +19,17 @@ let rec make_list l =
(* Return the list of elements of the rule. *) (* Return the list of elements of the rule. *)
let default_action (pl: string list) : string = let default_action (pl: string list) : string =
make_list (List.mapi (fun i e -> i) pl) (* make_list (List.mapi (fun i e -> i) pl) *)
"()"
let resolve_vars s = let resolve_vars s =
Str.global_replace (Str.regexp "\\$\\([0-9]+\\)") "p\\1" s Str.global_replace (Str.regexp "\\$\\([0-9]+\\)") "p\\1" s
let make_nt (table: string*string -> lltype list) (toks,nts,rules) oc n () = let make_nt (table: string*string -> lltype list) (toks,nts,rules) oc (n,ot) () =
Printf.fprintf oc "and parse_%s tokens () =\n" n; 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"; Printf.fprintf oc " begin match tokens with\n";
List.iteri List.iteri
(fun i t -> (fun i t ->
...@@ -40,47 +44,37 @@ let make_nt (table: string*string -> lltype list) (toks,nts,rules) oc n () = ...@@ -40,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) 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)) else Printf.fprintf oc " parse_%s tokens () >>= fun (p%d, tokens) ->\n" t (i+1))
pl; pl;
Printf.fprintf oc "\n" ; let act = match act with Some act -> act | _ -> default_action pl in
Printf.fprintf oc " let res =\n" ; Printf.fprintf oc " let res = %s in\n" (resolve_vars act);
(match act with Printf.fprintf oc " OK (res, tokens)\n" ;
| Some act -> Printf.fprintf oc " %s\n" (resolve_vars act) Printf.fprintf oc " end\n";
| _ ->
Printf.fprintf oc " %s\n" (resolve_vars (default_action pl))
);
Printf.fprintf oc " in OK (res, tokens)\n" ;
Printf.fprintf oc "end\n";
) )
toks; toks;
let expected = List.filter (fun t -> List.length (table (n,t)) > 0) toks in let expected = List.filter (fun t -> List.length (table (n,t)) > 0) toks in
Printf.fprintf oc " | tokens -> \n"; 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 " 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 " (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 " | 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 " | None -> Printf.sprintf \"Error while parsing %s\\n\" )^\n" n;
Printf.fprintf oc " Printf.sprintf \"Expected one of \"^\n"; Printf.fprintf oc " Printf.sprintf \"Expected one of {%%s}\"\n";
begin Printf.fprintf oc " (String.concat \", \" (List.map string_of_symbol [%s])) ^\n"
match expected with (String.concat ";" (List.map (fun s -> "default_"^s) expected)) ;
[] -> Printf.fprintf oc "Printf.sprintf \"{}\" ^\n" Printf.fprintf oc " Printf.sprintf \" but got '%%s' instead.\\n\" got\n ^ ";
| a::r -> Printf.fprintf oc " Printf.sprintf \" '%%s' \\n\" (String.concat \",\" (List.map (fun (x, _) -> string_of_symbol x) (List.take 10 tokens)))\n";
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.fprintf oc " )";
Printf.fprintf oc "\n end\n\n" Printf.fprintf oc "\n end\n\n"
let make_parser (table: string*string -> lltype list) let make_parser (table: string*string -> lltype list)
(toks,nts,rules,mlcode) (toks,nts,rules,mlcode)
(typ: (tokent * string) list) (typ: (tokent * string) list)
(nttyp: (nonterm * string) list)
oc () = oc () =
Stdlib.Option.iter (fun mlcode -> Printf.fprintf oc "\n\n%s\n\n" mlcode) mlcode; Stdlib.Option.iter (fun mlcode -> Printf.fprintf oc "\n\n%s\n\n" mlcode) mlcode;
List.iter (fun t -> List.iter (fun t ->
begin match List.assoc_opt t typ with begin match List.assoc_opt t typ with
| Some ty -> | Some ty ->
begin 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 " | %s _ -> true\n" t;
Printf.fprintf oc " | _ -> false\n"; Printf.fprintf oc " | _ -> false\n";
...@@ -89,11 +83,12 @@ let make_parser (table: string*string -> lltype list) ...@@ -89,11 +83,12 @@ let make_parser (table: string*string -> lltype list)
"string" -> "\"\"" "string" -> "\"\""
| "int" -> "0" | "int" -> "0"
| "bool" -> "false" | "bool" -> "false"
| "char" -> "'a'"
| _ -> failwith (Printf.sprintf "Don't know how to generate a default value of type %s" ty) | _ -> failwith (Printf.sprintf "Don't know how to generate a default value of type %s" ty)
) )
end end
| None -> begin | 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 " | %s -> true\n" t;
Printf.fprintf oc " | _ -> false\n"; Printf.fprintf oc " | _ -> false\n";
Printf.fprintf oc "let default_%s = %s\n" t t Printf.fprintf oc "let default_%s = %s\n" t t
...@@ -101,23 +96,23 @@ let make_parser (table: string*string -> lltype list) ...@@ -101,23 +96,23 @@ let make_parser (table: string*string -> lltype list)
end; end;
) toks; ) toks;
List.iter (fun t -> 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 begin match List.assoc_opt t typ with
| Some _ -> Printf.fprintf oc "| (%s(x),_) :: rtokens -> OK (x, rtokens)\n" t | Some _ -> Printf.fprintf oc "| (%s(x),_) :: rtokens -> OK (x, rtokens)\n" t
| None -> Printf.fprintf oc "| (%s,_) :: rtokens -> OK ((), rtokens)\n" t | None -> Printf.fprintf oc "| (%s,_) :: rtokens -> OK ((), rtokens)\n" t
end; end;
Printf.fprintf oc "| (x,Some pos) :: _ -> Error (Printf.sprintf \"At position %%s, expected %%s, got %%s.\\n\""; 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)"; Printf.fprintf oc " (string_of_position pos)\n";
Printf.fprintf oc " (string_of_symbol default_%s)" t; Printf.fprintf oc " (string_of_symbol default_%s)\n" t;
Printf.fprintf oc " (string_of_symbol x))"; Printf.fprintf oc " (string_of_symbol x))\n";
Printf.fprintf oc " | (x,None) :: _ -> Error (Printf.sprintf \"Expected %%s, got %%s.\\n\""; Printf.fprintf oc " | (x,None) :: _ -> Error (Printf.sprintf \"Expected %%s, got %%s.\\n\"\n";
Printf.fprintf oc " (string_of_symbol default_%s)" t; Printf.fprintf oc " (string_of_symbol default_%s)\n" t;
Printf.fprintf oc " (string_of_symbol x))"; 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; Printf.fprintf oc " | _ -> Error (Printf.sprintf \"Expected %%s, got EOF.\\n\" (string_of_symbol default_%s))\n" t;
) toks; ) toks;
Printf.fprintf oc "let rec ____unused = () \n"; Printf.fprintf oc "let rec ____unused = ()\n";
List.iter (fun n -> make_nt table (toks,nts,rules) oc n ()) nts 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_ordered start (toks,nts,rules) =
let nts = let nts =
...@@ -163,6 +158,9 @@ let _ = ...@@ -163,6 +158,9 @@ let _ =
iter_first (toks, nts, rules) (); iter_first (toks, nts, rules) ();
iter_follownt (toks, nts, rules) (); iter_follownt (toks, nts, rules) ();
fill_lltable (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 (match !table_file with
| Some tfile -> let oc = open_out tfile in | Some tfile -> let oc = open_out tfile in
print_html (toks, nts, rules) (Format.formatter_of_out_channel oc) (); print_html (toks, nts, rules) (Format.formatter_of_out_channel oc) ();
...@@ -179,6 +177,11 @@ let _ = ...@@ -179,6 +177,11 @@ let _ =
| None -> None | None -> None
| Some typ -> Some (t,typ) | Some typ -> Some (t,typ)
) gram.tokens) ) gram.tokens)
(List.filter_map (fun (t,o) ->
match o with
| None -> None
| Some typ -> Some (t,typ)
) gram.nonterms)
oc (); oc ();
close_out oc close_out oc
) )
#!/bin/bash #!/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 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 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,23 +2,23 @@ tokens SYM_EOF SYM_IDENTIFIER<string> SYM_INTEGER<int> SYM_PLUS SYM_MINUS SYM_AS ...@@ -2,23 +2,23 @@ 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_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_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 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 LPARAMS REST_PARAMS
non-terminals IDENTIFIER INTEGER non-terminals IDENTIFIER INTEGER
non-terminals GLOBDEF non-terminals FUNDEF FUNDEFS
non-terminals ADD_EXPRS ADD_EXPR non-terminals ADD_EXPRS ADD_EXPR
non-terminals MUL_EXPRS MUL_EXPR non-terminals MUL_EXPRS MUL_EXPR
non-terminals CMP_EXPRS CMP_EXPR non-terminals CMP_EXPRS CMP_EXPR
non-terminals REQ_EXPRS REQ_EXPR non-terminals EQ_EXPRS EQ_EXPR
axiom S axiom S
{ {
open Symbols open Symbols
open Utils
open Ast open Ast
open BatPrintf open BatPrintf
open BatBuffer open BatBuffer
open Batteries open Batteries
open Utils
(* TODO *) (* TODO *)
let resolve_associativity term other = let resolve_associativity term other =
...@@ -29,11 +29,4 @@ axiom S ...@@ -29,11 +29,4 @@ axiom S
} }
rules rules
S -> GLOBDEF SYM_EOF { Node (Tlistglobdef, [$1]) } S -> FUNDEFS SYM_EOF { Node (Tlistglobdef, []) }
IDENTIFIER -> SYM_IDENTIFIER { StringLeaf ($1) }
INTEGER -> SYM_INTEGER { IntLeaf ($1) }
GLOBDEF -> IDENTIFIER SYM_LPARENTHESIS LPARAMS SYM_RPARENTHESIS INSTR {
let fargs = $3 in
let instr = $5 in
Node (Tfundef, [$1; Node (Tfunargs, fargs) ; instr ])
}
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
<div id="memstate"></div> <div id="memstate"></div>
</div> </div>
<div id="expr"> <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> Result: <span id="expr_res"></span><hr>
<div id="subexprs"></div> <div id="subexprs"></div>
</div> </div>
......
...@@ -678,10 +678,10 @@ function handle_command(d){ ...@@ -678,10 +678,10 @@ function handle_command(d){
for(let [evar,loc] of Object.entries(fb['vars'])){ for(let [evar,loc] of Object.entries(fb['vars'])){
if(Object.keys(loc).includes("reg")){ 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"); .insert("br");
} else { } else {
p.insert("span").html("Var "+evar+": "+loc["stk"]) p.insert("span").html("Var "+evar+": Stk "+loc["stk"])
.insert("br"); .insert("br");
} }
} }
......