needs a LOT of cleaning, but basics of proof parser working
This commit is contained in:
parent
82213f0df8
commit
c4262a10e2
7 changed files with 153 additions and 94 deletions
|
|
@ -2,6 +2,7 @@ signature PARSEUTILS =
|
||||||
sig
|
sig
|
||||||
include PARSE
|
include PARSE
|
||||||
val >>= : 'a p * ('a -> 'b p) -> 'b p
|
val >>= : 'a p * ('a -> 'b p) -> 'b p
|
||||||
|
val >>=? : 'a p * ('a -> 'a p) -> 'a p
|
||||||
end
|
end
|
||||||
|
|
||||||
structure ParseUtils: PARSEUTILS =
|
structure ParseUtils: PARSEUTILS =
|
||||||
|
|
@ -10,10 +11,18 @@ struct
|
||||||
Parse (type token = Token.t val pp_token = Token.pp_token)
|
Parse (type token = Token.t val pp_token = Token.pp_token)
|
||||||
open ParseUtilsTemp
|
open ParseUtilsTemp
|
||||||
|
|
||||||
infix >>=
|
infix >>= >>=?
|
||||||
|
|
||||||
fun (p >>= q) ts =
|
fun (p >>= q) ts =
|
||||||
case p ts of
|
case p ts of
|
||||||
OK (v, r, ts') => q v ts'
|
OK (v, r, ts') => q v ts'
|
||||||
| NO e => NO e
|
| NO e => NO e
|
||||||
|
|
||||||
|
fun (p >>=? q) ts =
|
||||||
|
case p ts of
|
||||||
|
s1 as (OK (v, r, ts')) =>
|
||||||
|
(case q v ts' of
|
||||||
|
OK s2 => OK s2
|
||||||
|
| NO _ => s1)
|
||||||
|
| NO e => NO e
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
structure ProofParser: PARSER =
|
||||||
|
struct
|
||||||
|
type result = Proof.t
|
||||||
|
|
||||||
|
structure StringSet = Utils.StringSet
|
||||||
|
structure ArityMap = Utils.ArityMap
|
||||||
|
structure T = Token
|
||||||
|
|
||||||
|
type state =
|
||||||
|
{constants: StringSet.t, functions: ArityMap.t, relations: ArityMap.t}
|
||||||
|
|
||||||
|
open ParseUtils
|
||||||
|
infix >>> ->> >>- ?? ??? || oo oor ??* >>= >>=?
|
||||||
|
|
||||||
|
open Proof
|
||||||
|
|
||||||
|
fun number_p nil =
|
||||||
|
NO (Region.botloc, fn () => "expecting number but reached the end")
|
||||||
|
| number_p ((Token.NUMBER num, r) :: rest) = OK (num, r, rest)
|
||||||
|
| number_p ((t, r) :: rest) =
|
||||||
|
NO (#1 r, fn () =>
|
||||||
|
"expecting number but found token " ^ Token.pp_token t)
|
||||||
|
|
||||||
|
val const = Utils.const
|
||||||
|
val label_p =
|
||||||
|
(eat (T.KEYWORD T.Axiom) oo const Axiom)
|
||||||
|
|| (eat (T.KEYWORD T.AndI) oo const AndI)
|
||||||
|
|| (eat (T.KEYWORD T.AndE) oo const AndE)
|
||||||
|
|| (eat (T.KEYWORD T.OrI) oo const OrI)
|
||||||
|
|| (eat (T.KEYWORD T.OrE) oo const OrE)
|
||||||
|
|| (eat (T.KEYWORD T.ArrI) oo const ArrI)
|
||||||
|
|| (eat (T.KEYWORD T.ArrE) oo const ArrE)
|
||||||
|
|| (eat (T.KEYWORD T.NegI) oo const NegI)
|
||||||
|
|| (eat (T.KEYWORD T.NegE) oo const NegE)
|
||||||
|
|| (eat (T.KEYWORD T.RAA) oo const RAA)
|
||||||
|
|| (eat (T.KEYWORD T.IffI) oo const IffI)
|
||||||
|
|| (eat (T.KEYWORD T.IffE) oo const IffE)
|
||||||
|
|| (eat (T.KEYWORD T.EqI) oo const EqI)
|
||||||
|
|| (eat (T.KEYWORD T.EqE) oo const EqE)
|
||||||
|
|| (eat (T.KEYWORD T.ForallI) oo const ForallI)
|
||||||
|
|| (eat (T.KEYWORD T.ForallE) oo const ForallE)
|
||||||
|
|| (eat (T.KEYWORD T.ExistsI) oo const ExistsI)
|
||||||
|
|| (eat (T.KEYWORD T.ExistsE) oo const ExistsE)
|
||||||
|
|
||||||
|
fun fold_lines lines (_, NO l) = NO l
|
||||||
|
| fold_lines lines (line, OK (children, r, rest)) =
|
||||||
|
OK (List.nth (lines, line - 1) :: children, r, rest)
|
||||||
|
handle Subscript =>
|
||||||
|
NO (#1 r, fn () => "Invalid line reference " ^ (Int.toString line))
|
||||||
|
|
||||||
|
fun line_refs_p lines ts =
|
||||||
|
case (((number_p oo (fn x => [x])) ??* number_p) (Utils.flip op::)) ts of
|
||||||
|
OK (nums, r, rest) => foldl (fold_lines lines) (OK ([], r, rest)) nums
|
||||||
|
| NO l => NO l
|
||||||
|
|
||||||
|
fun refless_tag_p ts =
|
||||||
|
((eat T.LBRACKET ->> label_p >>- eat T.RBRACKET)
|
||||||
|
oo (fn label => (label, []))) ts
|
||||||
|
|
||||||
|
fun ref_tag_p lines =
|
||||||
|
eat T.LBRACKET ->> label_p >>> line_refs_p lines >>- eat T.RBRACKET
|
||||||
|
|
||||||
|
fun tag_p lines = refless_tag_p || ref_tag_p lines
|
||||||
|
|
||||||
|
fun line_p (state, lines) : Proof.t p =
|
||||||
|
((number_p >>- eat T.DOT oo const ())
|
||||||
|
->>
|
||||||
|
(FormulaParser.parse
|
||||||
|
{ binders = []
|
||||||
|
, constants = #constants state
|
||||||
|
, functions = #functions state
|
||||||
|
, relations = #relations state
|
||||||
|
}) >>> (tag_p lines))
|
||||||
|
oo
|
||||||
|
(fn (phi, (label, children)) =>
|
||||||
|
Proof {formula = phi, label = label, children = children})
|
||||||
|
|
||||||
|
fun all_lines_p (state, lines) : Proof.t p =
|
||||||
|
line_p (state, lines) >>=? (fn line => all_lines_p (state, line :: lines))
|
||||||
|
|
||||||
|
fun parse state ts =
|
||||||
|
all_lines_p (state, []) ts
|
||||||
|
end
|
||||||
|
|
@ -5,6 +5,8 @@ struct
|
||||||
|
|
||||||
fun map_token (Symb "(") = LPAREN
|
fun map_token (Symb "(") = LPAREN
|
||||||
| map_token (Symb ")") = RPAREN
|
| map_token (Symb ")") = RPAREN
|
||||||
|
| map_token (Symb "[") = LBRACKET
|
||||||
|
| map_token (Symb "]") = RBRACKET
|
||||||
| map_token (Symb ".") = DOT
|
| map_token (Symb ".") = DOT
|
||||||
| map_token (Symb ",") = COMMA
|
| map_token (Symb ",") = COMMA
|
||||||
| map_token (Symb "#") = HASH
|
| map_token (Symb "#") = HASH
|
||||||
|
|
@ -19,17 +21,20 @@ struct
|
||||||
(case KeywordMap.get (keywordMap, id) of
|
(case KeywordMap.get (keywordMap, id) of
|
||||||
SOME keyword => KEYWORD keyword
|
SOME keyword => KEYWORD keyword
|
||||||
| NONE => IDENT id)
|
| NONE => IDENT id)
|
||||||
| map_token (Num _) = ERR
|
| map_token (Num num) =
|
||||||
|
NUMBER (valOf (Int.fromString num))
|
||||||
|
|
||||||
fun const k _ = k
|
val is_num = (List.all Char.isDigit) o String.explode
|
||||||
|
fun is_id s =
|
||||||
|
((List.all Char.isAlphaNum) (String.explode s)) andalso not (is_num s)
|
||||||
|
|
||||||
val scan =
|
val scan =
|
||||||
map (fn (t, r) => (map_token t, r))
|
map (fn (t, r) => (map_token t, r))
|
||||||
o
|
o
|
||||||
tokenise
|
tokenise
|
||||||
{ sep_chars = "(),&|.#~"
|
{ sep_chars = "[](),&|.#~"
|
||||||
, symb_chars = "<=>"
|
, symb_chars = "<=>"
|
||||||
, is_id = (List.all Char.isAlphaNum) o String.explode
|
, is_id = is_id
|
||||||
, is_num = const false
|
, is_num = is_num
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
signature TOKEN =
|
|
||||||
sig
|
|
||||||
datatype keyword =
|
|
||||||
(* labels *)
|
|
||||||
Axiom
|
|
||||||
| AndI
|
|
||||||
| AndE
|
|
||||||
| OrI
|
|
||||||
| OrE
|
|
||||||
| ArrI
|
|
||||||
| ArrE
|
|
||||||
| NegI
|
|
||||||
| NegE
|
|
||||||
| RAA
|
|
||||||
| IffI
|
|
||||||
| IffE
|
|
||||||
| EqI
|
|
||||||
| EqE
|
|
||||||
| ForallI
|
|
||||||
| ForallE
|
|
||||||
| ExistsI
|
|
||||||
| ExistsE
|
|
||||||
|
|
||||||
(* formulas *)
|
|
||||||
| Forall
|
|
||||||
| Exists
|
|
||||||
|
|
||||||
structure KeywordMap: MAP where type key = string and type value = keyword
|
|
||||||
val keywordMap: KeywordMap.t
|
|
||||||
|
|
||||||
datatype t =
|
|
||||||
LPAREN
|
|
||||||
| RPAREN
|
|
||||||
| NEG
|
|
||||||
| AND
|
|
||||||
| OR
|
|
||||||
| EQ
|
|
||||||
| RARROW
|
|
||||||
| LRARROW
|
|
||||||
| DOT
|
|
||||||
| COMMA
|
|
||||||
| HASH
|
|
||||||
| KEYWORD of keyword
|
|
||||||
| IDENT of string
|
|
||||||
| ERR
|
|
||||||
|
|
||||||
val pp_token: t -> string
|
|
||||||
|
|
||||||
val infix_connective: t -> bool
|
|
||||||
val prefix_connective: t -> bool
|
|
||||||
end
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
structure Token: TOKEN =
|
structure Token =
|
||||||
struct
|
struct
|
||||||
datatype keyword =
|
datatype keyword =
|
||||||
Axiom
|
Axiom
|
||||||
|
|
@ -25,6 +25,8 @@ struct
|
||||||
datatype t =
|
datatype t =
|
||||||
LPAREN
|
LPAREN
|
||||||
| RPAREN
|
| RPAREN
|
||||||
|
| LBRACKET
|
||||||
|
| RBRACKET
|
||||||
| NEG
|
| NEG
|
||||||
| AND
|
| AND
|
||||||
| OR
|
| OR
|
||||||
|
|
@ -36,6 +38,7 @@ struct
|
||||||
| HASH
|
| HASH
|
||||||
| KEYWORD of keyword
|
| KEYWORD of keyword
|
||||||
| IDENT of string
|
| IDENT of string
|
||||||
|
| NUMBER of int
|
||||||
| ERR
|
| ERR
|
||||||
|
|
||||||
structure KeywordMap = Map (structure Ord = StringOrd type value = keyword)
|
structure KeywordMap = Map (structure Ord = StringOrd type value = keyword)
|
||||||
|
|
@ -58,13 +61,37 @@ struct
|
||||||
, ("ForallE", ForallE)
|
, ("ForallE", ForallE)
|
||||||
, ("ExistsI", ExistsI)
|
, ("ExistsI", ExistsI)
|
||||||
, ("ExistsE", ExistsE)
|
, ("ExistsE", ExistsE)
|
||||||
, ("Forall", Forall)
|
, ("forall", Forall)
|
||||||
, ("Exists", Exists)
|
, ("exists", Exists)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
val keywordToString =
|
||||||
|
fn Axiom => "Axiom"
|
||||||
|
| AndI => "AndI"
|
||||||
|
| AndE => "AndE"
|
||||||
|
| OrI => "OrI"
|
||||||
|
| OrE => "OrE"
|
||||||
|
| ArrI => "ArrI"
|
||||||
|
| ArrE => "ArrE"
|
||||||
|
| NegI => "NegI"
|
||||||
|
| NegE => "NegE"
|
||||||
|
| RAA => "RAA"
|
||||||
|
| IffI => "IffI"
|
||||||
|
| IffE => "IffE"
|
||||||
|
| EqI => "EqI"
|
||||||
|
| EqE => "EqE"
|
||||||
|
| ForallI => "ForallI"
|
||||||
|
| ForallE => "ForallE"
|
||||||
|
| ExistsI => "ExistsI"
|
||||||
|
| ExistsE => "ExistsE"
|
||||||
|
| Forall => "forall"
|
||||||
|
| Exists => "exists"
|
||||||
|
|
||||||
val pp_token =
|
val pp_token =
|
||||||
fn LPAREN => "("
|
fn LPAREN => "("
|
||||||
| RPAREN => ")"
|
| RPAREN => ")"
|
||||||
|
| LBRACKET => "["
|
||||||
|
| RBRACKET => "]"
|
||||||
| NEG => "~"
|
| NEG => "~"
|
||||||
| AND => "&"
|
| AND => "&"
|
||||||
| OR => "|"
|
| OR => "|"
|
||||||
|
|
@ -73,11 +100,11 @@ struct
|
||||||
| LRARROW => "<=>"
|
| LRARROW => "<=>"
|
||||||
| DOT => "."
|
| DOT => "."
|
||||||
| COMMA => ","
|
| COMMA => ","
|
||||||
| FORALL => "forall"
|
|
||||||
| EXISTS => "exists"
|
|
||||||
| ERR => "unk"
|
|
||||||
| HASH => "#"
|
| HASH => "#"
|
||||||
|
| KEYWORD keyword => keywordToString keyword
|
||||||
| IDENT s => s
|
| IDENT s => s
|
||||||
|
| NUMBER num => Int.toString num
|
||||||
|
| ERR => "unk"
|
||||||
|
|
||||||
val infix_connective =
|
val infix_connective =
|
||||||
fn AND => true | OR => true | RARROW => true | LRARROW => true | _ => false
|
fn AND => true | OR => true | RARROW => true | LRARROW => true | _ => false
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ $(SML_LIB)/basis/basis.mlb
|
||||||
../utils/utils.mlb
|
../utils/utils.mlb
|
||||||
../../../../github.com/diku-dk/sml-parse/parse.mlb
|
../../../../github.com/diku-dk/sml-parse/parse.mlb
|
||||||
../../../../github.com/diku-dk/sml-parse/simple_token.mlb
|
../../../../github.com/diku-dk/sml-parse/simple_token.mlb
|
||||||
TOKEN.sig
|
|
||||||
Token.sml
|
Token.sml
|
||||||
SCANNER.sig
|
SCANNER.sig
|
||||||
Scanner.sml
|
Scanner.sml
|
||||||
|
|
@ -11,4 +10,5 @@ ParseUtils.sml
|
||||||
PARSER.sig
|
PARSER.sig
|
||||||
TermParser.sml
|
TermParser.sml
|
||||||
FormulaParser.sml
|
FormulaParser.sml
|
||||||
|
ProofParser.sml
|
||||||
repl.sml
|
repl.sml
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
open Scanner
|
open Scanner
|
||||||
|
|
||||||
structure Testing:
|
structure Testing =
|
||||||
sig
|
(* sig *)
|
||||||
val parse_repl: string -> unit
|
(* val parse_repl: string -> unit *)
|
||||||
end =
|
(* end = *)
|
||||||
struct
|
struct
|
||||||
open FormulaParser
|
open ProofParser
|
||||||
open Utils
|
open Utils
|
||||||
open ParseUtils
|
open ParseUtils
|
||||||
open Scanner
|
open Scanner
|
||||||
|
|
@ -14,31 +14,17 @@ struct
|
||||||
val constants = StringSet.fromList ["zero"]
|
val constants = StringSet.fromList ["zero"]
|
||||||
val relations = ArityMap.fromList [("lt", 2)]
|
val relations = ArityMap.fromList [("lt", 2)]
|
||||||
val state =
|
val state =
|
||||||
{ binders = []
|
{functions = functions, constants = constants, relations = relations}
|
||||||
, functions = functions
|
|
||||||
, constants = constants
|
|
||||||
, relations = relations
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parse_repl s =
|
fun parse_repl s =
|
||||||
let
|
let val toks = scan {input = s, srcname = "repl"}
|
||||||
val toks = scan {input = s, srcname = "repl"}
|
in parse state toks
|
||||||
in
|
(* case parse state toks of *)
|
||||||
case parse state toks of
|
(* OK (t, _, []) => print ("Parsed successfully: " ^ Formula.pp t ^ "\n") *)
|
||||||
OK (t, _, []) => print ("Parsed successfully: " ^ Formula.pp t ^ "\n")
|
(* | OK (t, r, rest) => *)
|
||||||
| OK (t, r, rest) =>
|
(* print *)
|
||||||
print
|
(* ("Parsed '" ^ Formula.pp t ^ "' up to " ^ Region.pp r ^ ", but " *)
|
||||||
("Parsed '" ^ Formula.pp t ^ "' up to " ^ Region.pp r ^ ", but "
|
(* ^ Int.toString (length rest) ^ " tokens remain unparsed\n") *)
|
||||||
^ Int.toString (length rest) ^ " tokens remain unparsed\n")
|
(* | NO (r, err) => print ("ERROR: " ^ Region.ppLoc r ^ ", " ^ err () ^ "\n") *)
|
||||||
| NO (r, err) => print ("ERROR: " ^ Region.ppLoc r ^ ", " ^ err () ^ "\n")
|
|
||||||
end
|
end
|
||||||
end
|
end (* fun repl () = *) (* ( print "> " *) (* ; case (TextIO.inputLine TextIO.stdIn) of *) (* SOME s => (Testing.parse_repl s; repl ()) *) (* | NONE => () *) (* ) *) (* fun main () = repl () (1* val () = main () *1) *)
|
||||||
|
|
||||||
fun repl () =
|
|
||||||
( print "> "
|
|
||||||
; case (TextIO.inputLine TextIO.stdIn) of
|
|
||||||
SOME s => (Testing.parse_repl s; repl ())
|
|
||||||
| NONE => ()
|
|
||||||
)
|
|
||||||
|
|
||||||
fun main () = repl () (* val () = main () *)
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue