ConfigParseProc: MakeDoParsing.ParserProc ~ {
PROC [stream: STREAM, parserData: REF] RETURNS [parseData: ParseData]
AddDef: PROC [name: ROPE] = {locals.first ¬ CONS[name, locals.first]};
MaybeConsume:
PROC [moduleName:
ROPE] = {
FOR l:
LIST
OF
LIST
OF
ROPE ¬ locals, l.rest
WHILE l #
NIL
DO
FOR m:
LIST
OF
ROPE ¬ l.first, m.rest
WHILE m #
NIL
DO
IF m.first.Equal[moduleName] THEN RETURN;
ENDLOOP;
ENDLOOP;
requestsFileList ¬ CONS[moduleName, requestsFileList];
};
Consume:
PROC [fileName:
ROPE] ~ {
requestsFileList ¬ CONS[fileName, requestsFileList];
};
ConsumeSimple:
PROC [fileName:
ROPE] ~ {
staticRequestsFileList ¬ CONS[fileName, staticRequestsFileList];
};
NextToken: PROC RETURNS [ROPE] = {RETURN [source.GetTokenRope[MesaBreak].token]};
IsConfig:
PROC [word:
ROPE]
RETURNS [is:
BOOLEAN] = {
is ¬ word.Equal["CONFIGURATION"] OR word.Equal["CONFIG"];
sourceType ¬ $Config
};
ParseConfigDescription:
PROC = {
next: ROPE ¬ ParseCDirectory[];
next ¬ ParseCPacking[next];
next ¬ ParseConfiguration[next];
IF NOT next.Equal["."] THEN ERROR GotoSyntaxError;
};
ParseConfiguration:
PROC [first:
ROPE]
RETURNS [next:
ROPE] = {
IF NOT MesaLetter[first.Fetch[0]] THEN ERROR GotoSyntaxError;
IF NOT (next ¬ NextToken[]).Equal[":"] THEN ERROR GotoSyntaxError;
IF NOT IsConfig[next ¬ NextToken[]] THEN ERROR GotoSyntaxError;
next ¬ ParseConfigurationRemains[];
};
ParseConfigurationRemains:
PROC
RETURNS [next:
ROPE] = {
next ¬ ParseCHeadRemains[];
IF NOT (next.Equal["="] OR next.Equal["~"]) THEN ERROR GotoSyntaxError;
ParseCBody[];
next ¬ NextToken[];
};
ParseCBody:
PROC = {
next: ROPE ¬ NextToken[];
curly: BOOLEAN;
IF next.Equal["BEGIN"] THEN curly ¬ FALSE
ELSE IF next.Equal["{"] THEN curly ¬ TRUE
ELSE ERROR GotoSyntaxError;
locals ¬ CONS[NIL, locals];
next ¬ NextToken[];
DO
semiSeen: BOOL ¬ FALSE;
next ¬ ParseCStatement[next];
WHILE next.Equal[";"]
DO
next ¬ NextToken[];
semiSeen ¬ TRUE;
ENDLOOP;
IF next.Equal[IF curly THEN "}" ELSE "END"] THEN EXIT;
IF NOT semiSeen THEN ERROR GotoSyntaxError;
ENDLOOP;
locals ¬ locals.rest;
};
ParseCStatement:
PROC [first:
ROPE]
RETURNS [next:
ROPE] = {
next ¬ first;
IF next.Equal["["]
THEN
BEGIN
next ¬ ParseItemList[FALSE];
IF NOT next.Equal["]"] THEN ERROR GotoSyntaxError;
next ¬ NextToken[];
IF NOT next.Equal["←"] THEN ERROR GotoSyntaxError;
next ¬ ParseCExpression[];
END
ELSE
BEGIN
lhs, rhs: ROPE;
named: BOOL ¬ FALSE;
lhs ¬ rhs ¬ next;
IF named ¬ (next ¬ NextToken[]).Equal[":"]
THEN
BEGIN
IF IsConfig[rhs ¬ NextToken[]]
THEN {
AddDef[lhs];
next ¬ ParseConfigurationRemains[];
RETURN};
next ¬ NextToken[];
END;
IF next.Equal["←"]
THEN
BEGIN
AddDef[lhs];
next ¬ ParseCExpression[];
END
ELSE
BEGIN
IF named THEN AddDef[lhs];
MaybeConsume[rhs];
IF next.Equal["["]
THEN
BEGIN
IF NOT (next ¬ NextToken[]).Equal["]"] THEN next ¬ EatIDList[next, FALSE];
IF NOT next.Equal["]"] THEN ERROR GotoSyntaxError;
next ¬ ParseCLinks[];
END
ELSE
IF next.Equal["LINKS"]
THEN {
SIGNAL MakeDoParsing.SyntaxError[IO.PutFR["[] missing before %g", IO.int[source.GetIndex[]]]];
next ¬ ParseCLinks[next];
};
END;
END;
};
ParseCExpression:
PROC
RETURNS [next:
ROPE] = {
next ¬ ParseCRightSide[];
WHILE next.Equal["PLUS"]
DO
next ¬ ParseCRightSide[];
ENDLOOP;
WHILE next.Equal["THEN"]
DO
next ¬ ParseCRightSide[];
ENDLOOP;
};
ParseCRightSide:
PROC
RETURNS [next:
ROPE] = {
next ¬ ParseItem[NIL, TRUE];
IF next.Equal["["]
THEN
BEGIN
IF NOT (next ¬ NextToken[]).Equal["]"] THEN next ¬ EatIDList[next, FALSE];
IF NOT next.Equal["]"] THEN ERROR GotoSyntaxError;
next ¬ ParseCLinks[];
END;
};
ParseCHeadRemains:
PROC
RETURNS [next:
ROPE] = {
next ¬ ParseCLinks[];
next ¬ ParseImports[next];
next ¬ ParseCExports[next];
next ¬ ParseStatics[next];
next ¬ ParseDynamics[next];
next ¬ ParseControlClause[next];
};
ParseCLinks:
PROC [first:
ROPE ¬
NIL]
RETURNS [next:
ROPE] = {
next ¬ IF first # NIL THEN first ELSE NextToken[];
IF NOT next.Equal["LINKS"] THEN RETURN;
IF NOT (next ¬ NextToken[]).Equal[":"] THEN ERROR GotoSyntaxError;
next ¬ NextToken[];
IF NOT (next.Equal["CODE"] OR next.Equal["FRAME"]) THEN ERROR GotoSyntaxError;
next ¬ NextToken[];
};
ParseImports:
PROC [first:
ROPE]
RETURNS [next:
ROPE] = {
IF NOT first.Equal["IMPORTS"] THEN RETURN [first];
next ¬ ParseItemList[FALSE];
};
ParseCExports:
PROC [first:
ROPE]
RETURNS [next:
ROPE] = {
IF NOT first.Equal["EXPORTS"] THEN RETURN [first];
next ¬ ParseItemList[FALSE];
};
ParseStatics:
PROC [first:
ROPE]
RETURNS [next:
ROPE] = {
IF NOT first.Equal["STATIC"] THEN RETURN [first];
IF NOT (next ¬ NextToken[]).Equal["REQUESTS"] THEN ERROR GotoSyntaxError;
next ¬ ParseStringList[TRUE];
};
ParseDynamics:
PROC [first:
ROPE]
RETURNS [next:
ROPE] = {
IF NOT first.Equal["DYNAMIC"] THEN RETURN [first];
IF NOT (next ¬ NextToken[]).Equal["REQUESTS"] THEN ERROR GotoSyntaxError;
next ¬ ParseStringList[FALSE];
};
ParseControlClause:
PROC [first:
ROPE]
RETURNS [next:
ROPE] = {
IF NOT first.Equal["CONTROL"] THEN RETURN [first];
next ¬ EatIDList[NIL, FALSE];
};
ParseItemList:
PROC [notice:
BOOLEAN]
RETURNS [next:
ROPE] = {
DO
next ¬ ParseItem[NIL, notice];
IF NOT next.Equal[","] THEN EXIT;
ENDLOOP;
};
ParseItem:
PROC [first:
ROPE, notice:
BOOLEAN]
RETURNS [next:
ROPE] = {
lhs, rhs: ROPE;
named: BOOL ¬ FALSE;
lhs ¬ rhs ¬ IF first = NIL THEN NextToken[] ELSE first;
IF named ¬ (next ¬ NextToken[]).Equal[":"]
THEN
BEGIN
rhs ¬ NextToken[];
next ¬ NextToken[];
END;
IF notice
THEN {
IF named THEN AddDef[lhs];
MaybeConsume[rhs]};
};
ParseStringList:
PROC [notice:
BOOLEAN]
RETURNS [next:
ROPE] = {
DO
next ¬ ParseString[notice];
IF NOT next.Equal[","] THEN EXIT;
ENDLOOP;
};
ParseString:
PROC [notice:
BOOLEAN]
RETURNS [next:
ROPE] = {
string: ROPE;
string ¬ source.GetRopeLiteral[ !IO.Error => ERROR GotoSyntaxError];
next ¬ NextToken[];
IF notice
THEN {
ConsumeSimple[string]};
};
ParseCDirectory:
PROC
RETURNS [next:
ROPE] = {
firstClause: BOOL ¬ TRUE;
ParseClause:
PROC
RETURNS [next:
ROPE] = {
moduleName: ROPE ¬ "?";
fileName: ROPE ¬ "?";
next ¬ NextToken[];
IF firstClause
THEN
{firstClause ¬ FALSE; IF next.Equal[";"] THEN RETURN};
IF NOT MesaLetter[next.Fetch[0]] THEN ERROR GotoSyntaxError;
moduleName ¬ fileName ¬ next;
next ¬ NextToken[];
IF next.Equal[":"]
THEN
BEGIN
next ¬ NextToken[];
IF next.Equal["TYPE"]
THEN {
next ¬ NextToken[];
IF MesaLetter[next.Fetch[0]] THEN next ¬ NextToken[];
}
ELSE
IF next.Equal["FROM"]
THEN {
fileName ¬ source.GetRopeLiteral[];
next ¬ NextToken[];
}
ELSE ERROR GotoSyntaxError;
END;
Consume[fileName];
AddDef[moduleName];
};
locals ¬ CONS[NIL, locals];
IF NOT (next ¬ NextToken[]).Equal["DIRECTORY"] THEN RETURN;
DO
IF (next ¬ ParseClause[]).Equal[";"] THEN EXIT;
IF NOT next.Equal[","] THEN ERROR GotoSyntaxError;
ENDLOOP;
next ¬ NextToken[];
};
ParseCPacking:
PROC [first:
ROPE]
RETURNS [next:
ROPE] = {
next ¬ first;
WHILE next.Equal["PACK"]
DO
next ¬ EatIDList[NIL, FALSE];
IF NOT next.Equal[";"] THEN ERROR GotoSyntaxError;
next ¬ NextToken[];
ENDLOOP;
};
EatIDList:
PROC [first:
ROPE, notice:
BOOLEAN]
RETURNS [next:
ROPE] = {
next ¬ IF first = NIL THEN NextToken[] ELSE first;
DO
IF NOT MesaLetter[next.Fetch[0]] THEN ERROR GotoSyntaxError;
IF notice THEN Consume[next];
next ¬ NextToken[];
IF NOT next.Equal[","] THEN EXIT;
next ¬ NextToken[];
ENDLOOP;
};
DoIt:
PROC ~ {
ParseConfigDescription[!
GotoSyntaxError => {
SIGNAL MakeDoParsing.SyntaxError[IO.PutFR["Syntax error in; parse aborted at %g", [integer[source.GetIndex[]]]]];
GOTO Done
};
IO.EndOfStream => {
SIGNAL MakeDoParsing.SyntaxError[IO.PutFR["Premature end-of-file; parse aborted at %g", [integer[source.GetIndex[]]]]];
GOTO Done
};
];
};
source: IO.STREAM ~ IOTrueCommentFilter.CreateCommentFilterStream[stream];
sourceType: ATOM ¬ $Unknown;
locals: LIST OF LIST OF ROPE ¬ NIL;
requestsFileList: LIST OF ROPE ¬ NIL;
staticRequestsFileList: LIST OF ROPE ¬ NIL;
[] ¬ source.GetIndex[];
DoIt[];
parseData ¬ RefTab.Create[];
[] ¬ parseData.Insert[$SourceType, sourceType];
[] ¬ parseData.Insert[$Requests, requestsFileList];
[] ¬ parseData.Insert[$StaticRequests, staticRequestsFileList];
[] ¬ parseData.Insert[$Locals, ListOfListsToList[locals]];
RETURN [parseData];
};