210 lines
6.8 KiB
OCaml
210 lines
6.8 KiB
OCaml
|
open Lex
|
||
|
|
||
|
type parseResult =
|
||
|
| Success of inputStream
|
||
|
| Failure
|
||
|
;;
|
||
|
|
||
|
(*
|
||
|
E -> ER = E
|
||
|
E -> ER
|
||
|
ER -> ER + T
|
||
|
ER -> ER - T
|
||
|
ER -> T
|
||
|
T -> T * F
|
||
|
T -> T / F
|
||
|
T -> F
|
||
|
F -> - F
|
||
|
F -> ( E )
|
||
|
F -> ident
|
||
|
F -> true
|
||
|
F -> false
|
||
|
F -> number
|
||
|
*)
|
||
|
|
||
|
(*
|
||
|
LL(1) Règle de production / Symboles directeurs
|
||
|
#1 - E -> function ident fleche E { function }
|
||
|
#2 - E -> if E then E else E { if }
|
||
|
#5 - E -> ER EX | { -, number, ident, true, false, ( }
|
||
|
#6 - EX -> = ER EX | { = }
|
||
|
#7 - EX -> | { $, ), then, else }
|
||
|
#8 - ER -> T TX | { -, number, ident, true, false, ( }
|
||
|
#9 - TX -> + T TX | { + }
|
||
|
#10 - TX -> - T TX | { - }
|
||
|
#11 - TX -> | { $, =, ), then, else }
|
||
|
#12 - T -> F FX | { -, number, ident, true, false, ( }
|
||
|
#13 - FX -> * F FX | { * }
|
||
|
#14 - FX -> / F FX | { / }
|
||
|
#15 - FX -> | { $, +, -, =, ), then, else }
|
||
|
#16 - F -> - F | { - }
|
||
|
#17 - F -> number | { number }
|
||
|
#20 - F -> ident | { ident }
|
||
|
#21 - F -> true | { true }
|
||
|
#22 - F -> false | { false }
|
||
|
#23 - F -> ( E ) | { ( }
|
||
|
*)
|
||
|
|
||
|
(* accept : token -> inputStream -> parseResult *)
|
||
|
(* Vérifie que le premier token du flux d'entrée est bien le token attendu *)
|
||
|
(* et avance dans l'analyse si c'est le cas *)
|
||
|
let accept expected stream =
|
||
|
match (peekAtFirstToken stream) with
|
||
|
| token when (token = expected) ->
|
||
|
(print_endline (string_of_token token));
|
||
|
(Success (advanceInStream stream))
|
||
|
| _ -> Failure
|
||
|
;;
|
||
|
|
||
|
(* acceptIdent : inputStream -> parseResult *)
|
||
|
(* Vérifie que le premier token du flux d'entrée est bien un identifiant *)
|
||
|
(* et avance dans l'analyse si c'est le cas *)
|
||
|
let acceptIdent stream =
|
||
|
match (peekAtFirstToken stream) with
|
||
|
| (IdentToken nom) ->
|
||
|
(print_endline nom);
|
||
|
(Success (advanceInStream stream))
|
||
|
| _ -> Failure
|
||
|
;;
|
||
|
|
||
|
(* acceptNumber : inputStream -> parseResult *)
|
||
|
(* Vérifie que le premier token du flux d'entrée est bien un nombre *)
|
||
|
(* et avance dans l'analyse si c'est le cas *)
|
||
|
let acceptNumber stream =
|
||
|
match (peekAtFirstToken stream) with
|
||
|
| (NumberToken _) -> (Success (advanceInStream stream))
|
||
|
| _ -> Failure
|
||
|
;;
|
||
|
|
||
|
(* parseE : inputStream -> parseResult *)
|
||
|
(* Analyse du non terminal E *)
|
||
|
let rec parseE stream =
|
||
|
(*
|
||
|
(print_endline (string_of_stream stream));
|
||
|
*)
|
||
|
(print_endline "E");
|
||
|
(match (peekAtFirstToken stream) with
|
||
|
(* regle #5 - E -> ER EX | { -, number, ident, true, false, ( } *)
|
||
|
(* Symboles directeurs *)
|
||
|
| (IdentToken _) | (NumberToken _) | TrueToken | FalseToken |
|
||
|
MinusToken | LeftParenthesisToken ->
|
||
|
(* Regle *)
|
||
|
(* Analyse ER *)
|
||
|
(match (parseER stream) with
|
||
|
| (Success next) ->
|
||
|
(* En cas de succes, analyse EX *)
|
||
|
parseEX next
|
||
|
| _ -> Failure)
|
||
|
| _ -> Failure)
|
||
|
|
||
|
(* parseEX : inputStream -> parseResult *)
|
||
|
(* Analyse du non terminal EX *)
|
||
|
and parseEX stream =
|
||
|
(print_endline "EX");
|
||
|
(match (peekAtFirstToken stream) with
|
||
|
(* regle #6 - EX -> = ER EX | { = } *)
|
||
|
| EqualToken -> (match (accept EqualToken stream) with
|
||
|
| Success next -> (match (parseER next) with
|
||
|
| Success next2 -> (parseEX next2)
|
||
|
| _ -> Failure)
|
||
|
| _ -> Failure)
|
||
|
(* regle #7 - EX -> | { $, ) } *)
|
||
|
| EOSToken | RightParenthesisToken | ThenToken | ElseToken -> (Success stream)
|
||
|
| _ -> Failure)
|
||
|
|
||
|
(* parseER : inputStream -> parseResult *)
|
||
|
(* Analyse du non terminal ER *)
|
||
|
and parseER stream =
|
||
|
(print_endline "ER");
|
||
|
(match (peekAtFirstToken stream) with
|
||
|
(* regle #8 - ER -> T TX | { -, number, ident, true, false, ( } *)
|
||
|
| (IdentToken _) | (NumberToken _) | TrueToken | FalseToken | MinusToken | LeftParenthesisToken ->
|
||
|
(match (parseT stream) with
|
||
|
| Success next -> (parseTX next)
|
||
|
| _ -> Failure)
|
||
|
| _ -> Failure)
|
||
|
|
||
|
(* parseTX : inputStream -> parseResult *)
|
||
|
(* Analyse du non terminal TX *)
|
||
|
and parseTX stream =
|
||
|
(print_endline "TX");
|
||
|
(match (peekAtFirstToken stream) with
|
||
|
(* regle #9 - TX -> + T TX | { + } *)
|
||
|
| PlusToken -> (match (accept PlusToken stream) with
|
||
|
| Success next -> (
|
||
|
match (parseT next) with
|
||
|
| Success next -> (parseTX next)
|
||
|
| _ -> Failure)
|
||
|
| _ -> Failure)
|
||
|
(* regle #10 - TX -> - T TX | { - } *)
|
||
|
| MinusToken -> (match (accept MinusToken stream) with
|
||
|
| Success next -> (
|
||
|
match (parseT next) with
|
||
|
| Success next -> (parseTX next)
|
||
|
| _ -> Failure)
|
||
|
| _ -> Failure)
|
||
|
(* regle #11 - TX -> | { $, =, ) } *)
|
||
|
| EOSToken | EqualToken | RightParenthesisToken -> Success stream
|
||
|
| _ -> Failure)
|
||
|
|
||
|
(* parseT : inputStream -> parseResult *)
|
||
|
(* Analyse du non terminal T *)
|
||
|
and parseT stream =
|
||
|
(print_endline "T");
|
||
|
(match (peekAtFirstToken stream) with
|
||
|
(* regle #12 - T -> F FX | { -, number, ident, true, false, ( } *)
|
||
|
| (IdentToken _) | (NumberToken _) | TrueToken | FalseToken |
|
||
|
MinusToken | LeftParenthesisToken -> (match (parseF stream) with
|
||
|
| Success next -> (parseFX next)
|
||
|
| _ -> Failure)
|
||
|
| _ -> Failure)
|
||
|
|
||
|
(* parseFX : inputStream -> parseResult *)
|
||
|
(* Analyse du non terminal FX *)
|
||
|
and parseFX stream =
|
||
|
(print_endline "FX");
|
||
|
(match (peekAtFirstToken stream) with
|
||
|
(* regle #13 - FX -> * F FX | { * } *)
|
||
|
| TimesToken -> (match (accept TimesToken stream) with
|
||
|
| Success next -> (
|
||
|
match (parseF next) with
|
||
|
| Success next -> (parseFX next)
|
||
|
| _ -> Failure)
|
||
|
| _ -> Failure)
|
||
|
(* regle #14 - FX -> / F FX | { / } *)
|
||
|
| DivideToken -> (match (accept DivideToken stream) with
|
||
|
| Success next -> (
|
||
|
match (parseF next) with
|
||
|
| Success next -> (parseFX next)
|
||
|
| _ -> Failure)
|
||
|
| _ -> Failure)
|
||
|
(* regle #15 - FX -> | { $, +, -, =, ) } *)
|
||
|
| EOSToken | PlusToken | MinusToken | EqualToken | RightParenthesisToken -> (Success stream)
|
||
|
| _ -> Failure)
|
||
|
|
||
|
(* parseF : inputStream -> parseResult *)
|
||
|
(* Analyse du non terminal F *)
|
||
|
and parseF stream =
|
||
|
(print_endline "F");
|
||
|
(match (peekAtFirstToken stream) with
|
||
|
(* regle #16 - F -> - F | { - } *)
|
||
|
| MinusToken -> (match (accept MinusToken stream) with
|
||
|
| Success next -> (parseF next)
|
||
|
| _ -> Failure)
|
||
|
(* regle #17 - F -> number | { number } *)
|
||
|
| NumberToken _ -> (acceptNumber stream)
|
||
|
(* regle #20 - F -> ident | { ident } *)
|
||
|
| IdentToken _ -> (acceptIdent stream)
|
||
|
(* regle #21 - F -> true | { true } *)
|
||
|
| TrueToken -> (accept TrueToken stream)
|
||
|
(* regle #22 - F -> false | { false } *)
|
||
|
| FalseToken -> (accept FalseToken stream)
|
||
|
(* regle #23 - F -> ( E ) | { ( } *)
|
||
|
| LeftParenthesisToken -> (match (accept LeftParenthesisToken stream) with
|
||
|
| Success next -> (match (parseE next) with
|
||
|
| Success next2 -> (accept RightParenthesisToken next2)
|
||
|
| _ -> Failure)
|
||
|
| _ -> Failure)
|
||
|
| _ -> Failure)
|
||
|
;;
|