language-oberon-0.1.1: examples/AGRS/Parser2.Mod
MODULE Parser2;
IMPORT AGRS,Names,Library,Grammars;
CONST
MaxStrLength=Grammars.MaxStrLength;
VAR
sentenceName,sExprName,exprName,atomicName: AGRS.Name;
treeName,tree1Name,attributesName,attributes1Name,subSentenceName: AGRS.Name;
attributeName: AGRS.Name;
sequenceName,qualificationName,fieldName: AGRS.Name;
disjunctionName: AGRS.Name;
charName,stringName,numberName: AGRS.Name;
argNoName,numberToIdName,lhsName,rhsName,dummyName: AGRS.Name;
customName,customParsersName: AGRS.Name;
customIdTerm: AGRS.Field;
collection: AGRS.ClosedClass;
ruleParser,altBuilder,varParser,blockParser,classParser: AGRS.Name;
rulesName,varName,blockName,className,guardName: AGRS.Name;
rulesParser,alternativeName,blockLocalsName,guardParser: AGRS.Name;
PROCEDURE NewDisjunction(alt1,alt2: AGRS.Term): AGRS.Term;
VAR
newTerm: AGRS.Disjunction;
BEGIN
NEW(newTerm);
newTerm.Init(alt1);
newTerm.InitAlternative(alt2);
RETURN newTerm
END NewDisjunction;
PROCEDURE NewContinuation(base,cont: AGRS.Term): AGRS.Term;
VAR
newTerm: AGRS.SubTerm;
BEGIN
NEW(newTerm);
newTerm.Init(base);
newTerm.InitQuery(cont);
RETURN newTerm
END NewContinuation;
PROCEDURE NewTreeRoot(root: AGRS.Term): AGRS.Tree;
VAR
newTerm: AGRS.Tree;
BEGIN
NEW(newTerm);
newTerm.Init(root);
RETURN newTerm
END NewTreeRoot;
PROCEDURE NewClassRoot(root: AGRS.Term): AGRS.Tree;
VAR
newTerm: AGRS.Class;
BEGIN
NEW(newTerm);
newTerm.Init(root);
RETURN newTerm
END NewClassRoot;
PROCEDURE NewTree(base: AGRS.Tree; prop: AGRS.Name; value: AGRS.Term): AGRS.Tree;
BEGIN
base.AddProperty(prop,value);
RETURN base
END NewTree;
PROCEDURE NewGrammarTree(root,value: AGRS.Term): AGRS.Tree;
BEGIN
RETURN NewTree(NewTreeRoot(root),Grammars.grammarName,value)
END NewGrammarTree;
PROCEDURE NewOption(grammar: AGRS.Term): AGRS.Tree;
BEGIN
RETURN NewGrammarTree(Grammars.optionName,grammar)
END NewOption;
PROCEDURE NewCharTerminal(expect: CHAR): AGRS.Tree;
BEGIN
RETURN NewGrammarTree(Grammars.charTerminalParser,
Library.NewChar(expect))
END NewCharTerminal;
PROCEDURE NewStringTerminal(expect: ARRAY OF CHAR): AGRS.Term;
BEGIN
RETURN NewGrammarTree(Grammars.terminalName,
NewTree(NewTreeRoot(Grammars.stringParser),
Grammars.treeName,Library.NewString(Names.NewStringCopy(expect))))
END NewStringTerminal;
PROCEDURE NewAttribute(property: AGRS.Name; grammar: AGRS.Term): AGRS.Term;
VAR
temp: AGRS.Term;
BEGIN
NEW(temp);
temp.Init(property);
RETURN NewTree(NewGrammarTree(Grammars.attrName,grammar),
Grammars.propertyName,temp)
END NewAttribute;
PROCEDURE NumberToId;
VAR
n,newTerm: AGRS.Term;
BEGIN
n:= argNoName.Value();
WITH n: Library.Number DO
NEW(newTerm);
newTerm.Init(Names.FindOrdinalName(n.value));
Grammars.propertyName.Assign(newTerm);
AGRS.Continue;
Grammars.propertyName.Restore;
ELSE
AGRS.Fail;
END;
END NumberToId;
PROCEDURE ParseChar;
VAR
chRead,chResult: CHAR;
BEGIN
Grammars.Read(chRead);
IF chRead="'" THEN
Grammars.Read(chResult);
Grammars.Read(chRead);
IF chRead="'" THEN
IF Grammars.treeName.indirection=AGRS.Variable THEN
Grammars.treeName.Assign(Library.NewChar(chResult));
AGRS.Continue;
Grammars.treeName.Restore;
RETURN
END;
END;
END;
AGRS.Fail;
END ParseChar;
PROCEDURE ParseString;
VAR
ch,between: CHAR;
str: ARRAY MaxStrLength OF CHAR;
length: INTEGER;
BEGIN
Grammars.Read(between);
IF (between="'") OR (between='"') THEN
length:= 0;
Grammars.Read(ch);
WHILE (ch#between) & (ch#0DX) & (length<MaxStrLength) DO
str[length]:= ch;
INC(length);
Grammars.Read(ch);
END;
IF ch=between THEN
str[length]:= 0X;
IF Grammars.treeName.indirection=AGRS.Variable THEN
Grammars.treeName.Assign(
Library.NewString(Names.NewStringCopy(str)));
AGRS.Continue;
Grammars.treeName.Restore;
RETURN
END;
END;
END;
AGRS.Fail;
END ParseString;
PROCEDURE ParseNumber;
VAR
ch: CHAR;
minus: BOOLEAN;
x: INTEGER;
c: AGRS.TermStack;
BEGIN
Grammars.Read(ch);
IF ch='-' THEN
minus:= TRUE;
Grammars.Read(ch);
ELSE
minus:= FALSE;
IF ch='+' THEN
Grammars.Read(ch);
END
END;
IF (ch<'0') OR (ch>'9') THEN
AGRS.Fail;
RETURN
END;
x:= 0;
WHILE (ch>='0') & (ch<='9') DO
IF x <= (MAX(INTEGER)-ORD(ch)+ORD('0')) DIV 10 THEN
x:= 10*x+ORD(ch)-ORD('0');
END;
Grammars.Read(ch);
END;
IF minus THEN
x:= -x;
END;
Grammars.BackSpace;
IF Grammars.treeName.indirection=AGRS.Variable THEN
Grammars.treeName.Assign(Library.NewNumber(x));
c:= AGRS.continuation;
AGRS.Continue;
Grammars.treeName.Restore;
ELSE
AGRS.Fail;
END;
END ParseNumber;
PROCEDURE ParseCustom;
VAR
id,result: AGRS.Term;
BEGIN
id:= customIdTerm.Actual();
IF id.indirection=AGRS.Failure THEN
AGRS.Fail;
ELSE
AGRS.Push(id);
customParsersName.Reduce;
END;
END ParseCustom;
PROCEDURE ParseClass;
VAR
result: AGRS.Class;
t: AGRS.Term;
BEGIN
NEW(result);
result.Init(className);
Grammars.treeName.Assign(result);
treeName.Reduce;
Grammars.treeName.Restore;
t:= AGRS.result;
END ParseClass;
PROCEDURE BuildAlternative;
BEGIN
Grammars.treeName.Assign(
AGRS.MakeAlternative(lhsName.indirection,rhsName.indirection));
AGRS.Continue;
Grammars.treeName.Restore;
END BuildAlternative;
BEGIN
Grammars.DefineParser(charName,'P_CharacterAtom',ParseChar);
Grammars.DefineParser(stringName,'P_StringAtom',ParseString);
Grammars.DefineParser(numberName,'P_NumberAtom',ParseNumber);
Grammars.DefineParser(customName,'P_Custom',ParseCustom);
Grammars.DefineParser(classParser,'P_ParseCLASS',ParseClass);
Names.AddSystemName(altBuilder,'P_BuildAlternative',BuildAlternative);
Names.AddArgument(sentenceName,'P_Sentence');
Names.AddArgument(sExprName,'P_SExpr');
Names.AddArgument(exprName,'P_Expr');
Names.AddArgument(treeName,'P_Tree');
Names.AddArgument(tree1Name,'P_Tree1');
Names.AddArgument(attributesName,'P_Attributes');
Names.AddArgument(attributes1Name,'P_Attributes1');
Names.AddArgument(subSentenceName,'P_SubSentence');
Names.AddArgument(attributeName,'P_Attribute');
Names.AddArgument(disjunctionName,'P_Disjunction');
Names.AddArgument(sequenceName,'P_Sequence');
Names.AddArgument(qualificationName,'P_Qualification');
Names.AddArgument(fieldName,'P_Field');
Names.AddArgument(argNoName,'P_ArgNo');
Names.AddSystemName(numberToIdName,'P_NumberToName',NumberToId);
Names.AddArgument(lhsName,'P_LHS');
Names.AddArgument(rhsName,'P_RHS');
Names.AddArgument(alternativeName,'P_Alternative');
Names.AddArgument(varParser,'P_Var');
Names.AddArgument(ruleParser,'P_Rule');
Names.AddArgument(rulesParser,'P_Rules');
Names.AddArgument(guardParser,'P_Guard');
Names.AddArgument(rulesName,'RULE');
Names.AddArgument(varName,'VAR');
Names.AddArgument(blockName,'LOCAL');
Names.AddArgument(className,'CLASS');
Names.AddArgument(guardName,'GUARD');
Names.AddArgument(customParsersName,'P_CustomParsers');
Names.AddArgument(dummyName, '#Let');
Names.AddArgument(blockParser,'P_ParseBLOCK');
Names.AddArgument(blockLocalsName,'P_BlockLocals');
sentenceName.Init(NewDisjunction(sExprName,disjunctionName));
sExprName.Init(NewDisjunction(exprName,sequenceName));
Names.DefinePublicName(atomicName,'P_Atomic',
NewDisjunction(
charName,NewDisjunction(
stringName,
numberName)));
exprName.Init(NewDisjunction(
atomicName,NewDisjunction(
customName,NewDisjunction(
Grammars.nameParser,NewDisjunction(
qualificationName,NewDisjunction(
fieldName,
subSentenceName))))));
tree1Name.Init(AGRS.MakeLocalBlock(
NewTree(NewTreeRoot(dummyName),
argNoName,Library.NewNumber(0)),
attributesName));
treeName.Init(NewContinuation(
Grammars.idParser,NewContinuation(
NewCharTerminal('('),NewContinuation(
NewOption(tree1Name),
NewCharTerminal(')')))));
attributes1Name.Init(NewContinuation(
attributeName,
NewOption(NewContinuation(
NewCharTerminal(','),
attributesName))));
attributesName.Init(AGRS.MakeLocalBlock(
NewTree(NewTreeRoot(dummyName),
argNoName,NewTree(
NewTree(NewTreeRoot(Library.addName.indirection),
Library.argName1,argNoName),
Library.argName2,Library.NewNumber(1))),
attributes1Name));
(* attributesName.Init(NewTree(
NewTreeRoot(attributes1Name),
argNoName,NewTree(
NewTree(
NewTreeRoot(Library.addName.indirection),
Library.argName1,argNoName),
Library.argName2,Library.NewNumber(1))));
*)
subSentenceName.Init(NewContinuation(
NewCharTerminal('('),NewContinuation(
sentenceName,
NewCharTerminal(')'))));
attributeName.Init(NewDisjunction(
NewGrammarTree(
Grammars.genericAttrName,NewContinuation(
NewAttribute(Grammars.propertyName,
Grammars.nameParser),NewContinuation(
NewCharTerminal('='),
NewAttribute(Grammars.valueName,exprName)))),
NewContinuation(
numberToIdName,
NewGrammarTree(Grammars.attrName,exprName))));
disjunctionName.Init(NewGrammarTree(
Grammars.disjunctionName,NewContinuation(
NewAttribute(Library.argName1,sExprName),NewContinuation(
NewCharTerminal('|'),
NewAttribute(Library.argName2,sentenceName)))));
sequenceName.Init(NewGrammarTree(
Grammars.continuationName,NewContinuation(
NewAttribute(Library.argName1,exprName),NewContinuation(
NewCharTerminal(';'),
NewAttribute(Library.argName2,sExprName)))));
qualificationName.Init(NewGrammarTree(
Grammars.continuationName,NewContinuation(
NewAttribute(Library.argName1,Grammars.nameParser),NewContinuation(
NewCharTerminal('.'),
NewAttribute(Library.argName2,NewDisjunction(
treeName,
qualificationName))))));
fieldName.Init(NewGrammarTree(
Grammars.fieldName,NewContinuation(
NewAttribute(Library.argName1,Grammars.nameParser),NewContinuation(
NewCharTerminal('.'),
NewAttribute(Library.argName2,NewDisjunction(
Grammars.nameParser,
fieldName))))));
blockParser.Init(NewContinuation(
NewStringTerminal('LOCAL'),
NewGrammarTree(
Grammars.blockName,NewContinuation(
NewTree(
NewTreeRoot(Names.localName),
Names.bodyName,blockLocalsName),
NewAttribute(Grammars.rootName,sentenceName)))));
blockLocalsName.Init(NewContinuation(
NewGrammarTree(
Grammars.genericAttrName,NewContinuation(
NewAttribute(Grammars.propertyName,
Grammars.nameParser),
NewAttribute(Grammars.valueName,
NewTree(
NewTreeRoot(dummyName),
Grammars.treeName,AGRS.Variable)))),
NewDisjunction(
NewStringTerminal('IN'),
NewContinuation(
NewCharTerminal(','),
blockLocalsName))));
varParser.Init(NewContinuation(
NewStringTerminal('VAR'),
NewTree(
NewClassRoot(dummyName),
Grammars.treeName,AGRS.Variable)));
ruleParser.Init(NewContinuation(
NewStringTerminal('RULE'),NewContinuation(
NewCharTerminal('('),
rulesParser)));
rulesParser.Init(NewGrammarTree(
Grammars.disjunctionName,NewContinuation(
NewAttribute(Library.argName1,alternativeName),
NewAttribute(Library.argName2,NewDisjunction(
NewContinuation(
NewCharTerminal(')'),
NewTree(NewClassRoot(Grammars.constructName),
Grammars.rootName,AGRS.failName)),
NewContinuation(
NewCharTerminal(','),
rulesParser))))));
alternativeName.Init(NewContinuation(
NewTree(NewTreeRoot(dummyName), (* shall it stay class? *)
Grammars.treeName,NewClassRoot(dummyName)),NewContinuation(
NewAttribute(lhsName,treeName),NewContinuation(
NewCharTerminal('='),NewContinuation(
NewAttribute(rhsName,sExprName),NewContinuation(
Grammars.treeName,
altBuilder))))));
guardParser.Init(NewContinuation(
NewStringTerminal('GUARD'),
NewTree(
NewClassRoot(dummyName),
Grammars.treeName,AGRS.GuardTrap)));
Grammars.grammarName.Init(sentenceName);
NEW(customIdTerm);
customIdTerm.Init(Grammars.idParser);
customIdTerm.InitQuery(Grammars.treeName);
NEW(collection);
collection.Init(Names.SystemRoot);
collection.AddProperty(rulesName,ruleParser);
collection.AddProperty(varName,varParser);
collection.AddProperty(blockName,blockParser);
collection.AddProperty(className,classParser);
collection.AddProperty(guardName,guardParser);
collection.AddProperty(AGRS.otherwise,treeName);
customParsersName.Init(collection);
END Parser2.