added negation and cleaned up/fixed parsing

This commit is contained in:
William Ball 2024-08-13 18:55:21 -07:00
parent 607b9f1d7d
commit 68de6a806b
3 changed files with 63 additions and 39 deletions

View file

@ -23,36 +23,34 @@ struct
open Formula open Formula
open Scanner open Scanner
val prec = exception NotOperator of token
fn AND => (7, 6)
| OR => (5, 4) val infix_table =
| RARROW => (2, 3) fn AND => (40, 41, Conj)
| LRARROW => (1, 1) | OR => (30, 31, Disj)
| _ => (~1, ~1) | RARROW => (21, 20, Impl)
| LRARROW => (10, 10, Iff)
| t => (100, 100, fn _ => raise NotOperator t)
val prefix_table =
fn NEG => ((), 50, Neg) | t => ((), 100, fn _ => raise NotOperator t)
exception NotOperator exception NotOperator
val comb_func =
fn AND => Conj
| OR => Disj
| RARROW => Impl
| LRARROW => Iff
| _ => fn (_, _) => raise NotOperator
fun parse fun parse
(state as (state as
{ binders = binders { binders = binders
, constants = constants , constants = constants
, functions = functions , functions = functions
, relations = relations , relations = relations
}) = }) ts =
let let
val termState = val termState =
{binders = binders, constants = constants, functions = functions} {binders = binders, constants = constants, functions = functions}
val term_p = TermParser.parse termState val term_p = TermParser.parse termState
fun formula_p ts = parse state ts fun parse_full ts = parse state ts
fun equal_p ts = fun equal_p ts =
((term_p >>- eat EQ >>> term_p) oo Equal) ts ((term_p >>- eat EQ >>> term_p) oo Equal) ts
@ -107,30 +105,49 @@ struct
NO (Region.botloc, fn () => NO (Region.botloc, fn () =>
"expecting identifier but reached the end") "expecting identifier but reached the end")
val atomic_p = exception ParseError of locerr
bottom_p || equal_p || forall_p || exists_p || relation_p
|| (eat LPAREN ->> formula_p >>- eat RPAREN)
fun comb_p mprec [] = fun unwrap (OK c) = c
| unwrap (NO l) = raise ParseError l
fun atomic_p ts =
(equal_p || bottom_p || relation_p || forall_p || exists_p
|| (eat LPAREN ->> formula_p 0 >>- eat RPAREN)) ts
and formula_p mprec [] =
NO (Region.botloc, fn () => "expecting formula but reached the end") NO (Region.botloc, fn () => "expecting formula but reached the end")
| comb_p mprec ts = | formula_p mp (ts as ((t, r) :: rest)) =
case atomic_p ts of let
NO e => NO e (* get first term atomic or prefix *)
| OK (v, r, []) => OK (v, r, []) val (lhs, r, rest') = unwrap
| OK (v, r1, ts as (t, r) :: rest) => (if prefix_connective t then
let let val ((), rp, comb) = prefix_table t
val (lprec, rprec) = prec t in (formula_p rp oo comb) rest
val comb = comb_func t end
in else
if lprec < mprec then atomic_p ts)
if connective t then
((comb_p 0) oo (fn res => comb (v, res))) rest (* loop through the rest while the precedence is high enough *)
fun loop (lhs, r, []) = OK (lhs, r, [])
| loop (lhs, r, ts as (t, _) :: rest) =
if infix_connective t then
let
val (lp, rp, comb) = infix_table t
in
if lp < mp then
OK (lhs, r, ts)
else
let val (rhs, r'', rest') = unwrap (formula_p rp rest)
in loop (comb (lhs, rhs), r'', rest')
end
end
else else
OK (v, r1, ts) OK (lhs, r, ts)
else in
((comb_p rprec) oo (fn res => comb (v, res))) rest loop (lhs, r, rest')
end end
in in
comb_p 0 formula_p 0 ts
handle ParseError l => NO l
end end
end end

View file

@ -3,6 +3,7 @@ sig
datatype token = datatype token =
LPAREN LPAREN
| RPAREN | RPAREN
| NEG
| AND | AND
| OR | OR
| EQ | EQ
@ -19,5 +20,6 @@ sig
val scan: {srcname: string, input: string} -> (token * Region.reg) list val scan: {srcname: string, input: string} -> (token * Region.reg) list
val pp_token: token -> string val pp_token: token -> string
val connective: token -> bool val infix_connective: token -> bool
val prefix_connective: token -> bool
end end

View file

@ -5,6 +5,7 @@ struct
datatype token = datatype token =
LPAREN LPAREN
| RPAREN | RPAREN
| NEG
| AND | AND
| OR | OR
| EQ | EQ
@ -23,6 +24,7 @@ struct
| map_token (Symb ".") = DOT | map_token (Symb ".") = DOT
| map_token (Symb ",") = COMMA | map_token (Symb ",") = COMMA
| map_token (Symb "#") = HASH | map_token (Symb "#") = HASH
| map_token (Symb "~") = NEG
| map_token (Symb "&") = AND | map_token (Symb "&") = AND
| map_token (Symb "|") = OR | map_token (Symb "|") = OR
| map_token (Symb "=") = EQ | map_token (Symb "=") = EQ
@ -40,7 +42,7 @@ struct
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 = (List.all Char.isAlphaNum) o String.explode
, is_num = const false , is_num = const false
@ -49,6 +51,7 @@ struct
val pp_token = val pp_token =
fn LPAREN => "(" fn LPAREN => "("
| RPAREN => ")" | RPAREN => ")"
| NEG => "~"
| AND => "&" | AND => "&"
| OR => "|" | OR => "|"
| EQ => "=" | EQ => "="
@ -62,6 +65,8 @@ struct
| HASH => "#" | HASH => "#"
| IDENT s => s | IDENT s => s
val connective = val infix_connective =
fn AND => true | OR => true | RARROW => true | LRARROW => true | _ => false fn AND => true | OR => true | RARROW => true | LRARROW => true | _ => false
val prefix_connective = fn NEG => true | _ => false
end end