ReadFormula:
PUBLIC
PROC [in:
IO.
STREAM, formulaAlgebra:
AC.Structure]
RETURNS [formula: Formula, termChar:
CHAR] ~ {
Assumes that formula is quantifier-free, and is either an atomic formula, a formula enclosed in parentheses, the negation of a formula enclosed in parenthesis, a disjunction of formulas, or a conjunction of formulas. Termination is either by end of stream, or $, or an extra ) (for recursive calls). If by end of stream, then termChar = NUL. If by $, then the $ is removed from in. If by ), the ) is not removed from in.
char: CHAR;
junct: Formula;
list, listTail: LIST OF Formula ← NIL;
formulaAlgebraData: FormulaAlgebraData ← NARROW[formulaAlgebra.instanceData];
polynomialRing: AC.Structure ← formulaAlgebraData.polynomialRing;
polyRingData: POL.PolynomialRingData ← NARROW[polynomialRing.instanceData];
ReadJunct:
PROC ~ {
Skips preceding white space and read a junct. At exit, char is "terminating char", i.e. first nonblank char beyond junct (NUL if end of stream). char has been removed if = $, otherwise not.
[]← in.SkipWhitespace[];
char ← in.PeekChar[];
IF polynomialRing.class.legalFirstChar[char, polynomialRing]
THEN
-- unparenthesized atomic formula
[junct, char] ← ReadAtomicFormula[in, formulaAlgebra]
ELSE
IF char='~
THEN {
char ← in.GetChar[]; -- remove tilde
[]← in.SkipWhitespace[];
char ← in.PeekChar[];
IF char='(
THEN {
[] ← in.GetChar[]; -- remove left paren
[junct, char] ← ReadFormula[in, formulaAlgebra];
IF char#') THEN ERROR;
junct ←
NEW[AC.ObjectRec ← [
structure: formulaAlgebra,
data:
NEW[FormulaDataRec ← [
numFreeVars: polyRingData.allVariables.lengthPlus1 - 1,
atomicMatrix: FALSE,
mainOperator: FormulaOperators.FromRope["not", FormulaOperators.Operators],
operands: LIST[junct]
]]
]];
[] ← in.GetChar[]; -- remove right paren
[]← in.SkipWhitespace[];
IF in.EndOf[] THEN {char ← 000C; RETURN};
char ← in.PeekChar[];
IF char = '$ THEN [] ← in.GetChar[]; -- remove $
RETURN;
}
ELSE ERROR;
}
ELSE
IF char='(
THEN {
[] ← in.GetChar[]; -- move past left paren
[junct, char] ← ReadFormula[in, formulaAlgebra];
IF char#') THEN ERROR;
[] ← in.GetChar[]; -- remove right paren
[]← in.SkipWhitespace[];
IF in.EndOf[] THEN {char ← 000C; RETURN};
char ← in.PeekChar[];
IF char = '$ THEN [] ← in.GetChar[]; -- remove $
RETURN;
}
ELSE ERROR;
};
ReadJunct[]; formula ← junct;
IF in.EndOf[] THEN RETURN[formula, char];
IF char='|
THEN {
list ← listTail ← LIST[junct];
WHILE char='
|
DO
[] ← in.GetChar[]; -- remove |
ReadJunct[];
listTail ← listTail.rest ← LIST[junct];
ENDLOOP;
formula ←
NEW[AC.ObjectRec ← [
structure: formulaAlgebra,
data:
NEW[FormulaDataRec ← [
numFreeVars: polyRingData.allVariables.lengthPlus1 - 1,
atomicMatrix: FALSE,
mainOperator: FormulaOperators.FromRope["or", FormulaOperators.Operators],
operands: list
]]
]];
};
IF char='&
THEN {
list ← listTail ← LIST[junct];
WHILE char='
&
DO
[] ← in.GetChar[]; -- remove |
ReadJunct[];
listTail ← listTail.rest ← LIST[junct];
ENDLOOP;
formula ←
NEW[AC.ObjectRec ← [
structure: formulaAlgebra,
data:
NEW[FormulaDataRec ← [
numFreeVars: polyRingData.allVariables.lengthPlus1 - 1,
atomicMatrix: FALSE,
mainOperator: FormulaOperators.FromRope["and", FormulaOperators.Operators],
operands: list
]]
]];
};
RETURN[formula, char];
};
ReadAtomicFormula:
PUBLIC
PROC [in:
IO.
STREAM, formulaAlgebra:
AC.Structure]
RETURNS [formula: Formula, termChar:
CHAR] ~ {
May be terminated by end of stream, or by &, |, ), or $. If by end of stream, then termChar ← NUL. If by $, then $ has been removed from in. If by any of the other chars, then not removed from in.
leftPoly, rightPoly, formulaPoly: POL.Polynomial;
leftDPoly, rightDPoly: DP.DPolynomial;
firstRelationChar: CHAR;
relation: Rope.ROPE;
polySign: Basics.Comparison;
formulaAlgebraData: FormulaAlgebraData ← NARROW[formulaAlgebra.instanceData];
polynomialRing: AC.Structure ← formulaAlgebraData.polynomialRing;
polyRingData: POL.PolynomialRingData ← NARROW[polynomialRing.instanceData];
V: VARS.VariableSeq ← polyRingData.allVariables;
RelationProc:
DP.TermCharProc = {
SELECT char
FROM
'<, '>, '=, '#,'~ => RETURN[TRUE];
ENDCASE => RETURN[FALSE];
};
EndAtomicFormulaProc:
DP.TermCharProc = {
SELECT char
FROM
'&, '|, '), '$ => RETURN[TRUE];
ENDCASE => RETURN[FALSE];
};
[leftDPoly, firstRelationChar] ← DP.ReadDPoly[in, V, polyRingData.baseCoeffRing, RelationProc];
IF in.EndOf[] OR firstRelationChar = '$ THEN ERROR; -- check that we saw a relation char
[] ← in.GetChar[]; -- remove firstRelationChar
leftPoly ← NARROW[POL.PolyFromDPoly[leftDPoly, polynomialRing]];
SELECT firstRelationChar
FROM
'< => IF in.PeekChar[] = '= THEN {relation ← "le"; [] ← in.GetChar[] } ELSE relation ← "lt";
'> => IF in.PeekChar[] = '= THEN {relation ← "ge"; [] ← in.GetChar[] } ELSE relation ← "gt";
'~ => IF in.PeekChar[] = '= THEN {relation ← "ne"; [] ← in.GetChar[] } ELSE ERROR; -- no other valid meaning for ~ here
'= => relation ← "eq";
'# => relation ← "ne";
ENDCASE => ERROR; -- only cases possible
[rightDPoly, termChar] ← DP.ReadDPoly[in, V, polyRingData.baseCoeffRing, EndAtomicFormulaProc];
rightPoly ← NARROW[POL.PolyFromDPoly[rightDPoly, polynomialRing]];
formulaPoly ← NARROW[ polynomialRing.class.subtract[leftPoly, rightPoly] ];
IF polynomialRing.class.ordered
THEN
polySign ← polynomialRing.class.sign[formulaPoly]
IF polySign = less
THEN {
formulaPoly ← NARROW[ polynomialRing.class.negate[formulaPoly] ]; -- polynomial in atomic formula must be nonnegative
SELECT relation
FROM
"lt" => relation ← "gt";
"le" => relation ← "ge";
"gt" => relation ← "lt";
"ge" => relation ← "le";
ENDCASE;
};
formula ←
NEW[AC.ObjectRec ← [
structure: formulaAlgebra,
data:
NEW[FormulaDataRec ← [
numFreeVars: polyRingData.allVariables.lengthPlus1 - 1,
atomicMatrix: TRUE,
mainOperator: FormulaOperators.FromRope[relation, FormulaOperators.Operators],
polynomial: formulaPoly
]]
]];
RETURN[formula, termChar];
};
FormulaToRope:
PUBLIC
PROC [in: Formula, termRope: Rope.
ROPE ←
NIL]
RETURNS [out: Rope.
ROPE] ~ {
formulaAlgebraData: FormulaAlgebraData ← NARROW[in.structure.instanceData];
polynomialRing: AC.Structure ← formulaAlgebraData.polynomialRing;
polyRingData: POL.PolynomialRingData ← NARROW[polynomialRing.instanceData];
V: VARS.VariableSeq ← polyRingData.allVariables;
coeffRing: AC.Structure ← polyRingData.baseCoeffRing;
inData: FormulaData ← NARROW[in.data];
IF inData.atomicMatrix
THEN {
mainOperatorData: FormulaOperators.OperatorData ← NARROW[inData.mainOperator.data];
out ← Rope.Concat[ "( ", POL.PolyToRope[inData.polynomial, ""]];
SELECT mainOperatorData^
FROM
lt => out ← Rope.Concat[out, " < 0 )"];
le => out ← Rope.Concat[out, " <= 0 )"];
gt => out ← Rope.Concat[out, " > 0 )"];
ge => out ← Rope.Concat[out, " >= 0 )"];
eq => out ← Rope.Concat[out, " = 0 )"];
ne => out ← Rope.Concat[out, " # 0 )"];
ENDCASE;
RETURN[ Rope.Concat[out, termRope] ];
}
ELSE {
terms: LIST OF Formula ← inData.operands;
mainOperatorData: FormulaOperators.OperatorData ← NARROW[inData.mainOperator.data];
IF mainOperatorData^ # not THEN out ← "( " ELSE out ← "~ ( ";
WHILE terms#
NIL
DO
out ← Rope.Concat[out, FormulaToRope[terms.first] ];
terms ← terms.rest;
IF terms#
NIL
THEN
SELECT mainOperatorData^
FROM
and => out ← Rope.Concat[out, " & "];
or => out ← Rope.Concat[out, " | "];
ENDCASE => ERROR; -- shouldn't be in here when mainOperator = not
ENDLOOP;
out ← Rope.Cat[out, " )", termRope];
};
};
MakeFormulaExpr:
PUBLIC
PROC [in: Formula]
RETURNS [out: MathExpr.
EXPR] ~ {
formulaAlgebraData: FormulaAlgebraData ← NARROW[in.structure.instanceData];
polynomialRing: AC.Structure ← formulaAlgebraData.polynomialRing;
polyRingData: POL.PolynomialRingData ← NARROW[polynomialRing.instanceData];
V: VARS.VariableSeq ← polyRingData.allVariables;
coeffRing: AC.Structure ← polyRingData.baseCoeffRing;
inData: FormulaData ← NARROW[in.data];
IF inData.atomicMatrix
THEN {
polynomial: POL.Polynomial ← inData.polynomial;
mainOperatorData: FormulaOperators.OperatorData ← NARROW[inData.mainOperator.data];
SELECT mainOperatorData^
FROM
lt =>
RETURN[MathConstructors.MakeLtFormula[
POL.MakePolyExpr[polynomial], MathConstructors.MakeInt["0"] ] ];
le =>
RETURN[MathConstructors.MakeLeFormula[
POL.MakePolyExpr[polynomial], MathConstructors.MakeInt["0"] ] ];
gt =>
RETURN[MathConstructors.MakeGtFormula[
POL.MakePolyExpr[polynomial], MathConstructors.MakeInt["0"] ] ];
ge =>
RETURN[MathConstructors.MakeGeFormula[
POL.MakePolyExpr[polynomial], MathConstructors.MakeInt["0"] ] ];
eq =>
RETURN[MathConstructors.MakeEqFormula[
POL.MakePolyExpr[polynomial], MathConstructors.MakeInt["0"] ] ];
ne =>
RETURN[MathConstructors.MakeNotEqFormula[
POL.MakePolyExpr[polynomial], MathConstructors.MakeInt["0"] ] ];
ENDCASE;
}
ELSE {
terms: LIST OF Formula ← inData.operands;
firstTermExpr: MathExpr.EXPR ← MakeFormulaExpr[terms.first];
mainOperatorData: FormulaOperators.OperatorData ← NARROW[inData.mainOperator.data];
IF mainOperatorData^ = not
THEN
RETURN[MathConstructors.MakeNot[MathConstructors.MakeParen[firstTermExpr] ] ];
out ← MathConstructors.MakeParen[firstTermExpr];
terms ← terms.rest;
WHILE terms#
NIL
DO
SELECT mainOperatorData^
FROM
and => out ← MathConstructors.MakeAnd[out, MathConstructors.MakeParen[MakeFormulaExpr[terms.first] ] ];
or => out ← MathConstructors.MakeOr[out, MathConstructors.MakeParen[MakeFormulaExpr[terms.first] ] ];
ENDCASE => ERROR; -- shouldn't be in here when mainOperator = not
terms ← terms.rest;
ENDLOOP;
};
};