obliqparse/src/ObliqParser.m3


 Copyright 1991 Digital Equipment Corporation.               
 Distributed only by permission.                             

MODULE ObliqParser;
IMPORT Thread, Rd, TextRd, Bundle, ObliqBdl, SynWr, SynScan, SynParse, MetaParser, ObParseFrame, ObTree, ObValue, ObParseTree, ObFrame, Obliq, SynLocation, ObErr, Process;
FROM ObValue IMPORT Error, Exception;

  VAR metaParserMutex: Thread.Mutex;
      obliqClauseList: MetaParser.ClauseList;

  VAR setupDone := FALSE;

  PROCEDURE PackageSetup() =
  BEGIN
    SynParse.PackageSetup();
    TRY
      MetaParser.PackageSetup(); (* NOWARN *)
    EXCEPT
    | SynParse.Fail =>
      Process.Crash("Fatal error trying to parse MetaSyn grammar");
    END;
    Obliq.PackageSetup();

    IF NOT setupDone THEN
      setupDone := TRUE;
      ObFrame.Setup();
      ObParseTree.Setup();
      ObParseFrame.Setup();
      metaParserMutex := NEW(Thread.Mutex);
      obliqClauseList := NIL;
    END;
  END PackageSetup;

  PROCEDURE New(swr: SynWr.T): SynParse.T =
  VAR parser: SynParse.T; actions: MetaParser.ActionTable;
  BEGIN
    LOCK metaParserMutex DO
      TRY
        IF obliqClauseList = NIL THEN
          actions := MetaParser.NewActionTable();
          ObParseFrame.RegisterActions(actions);
          ObParseTree.RegisterActions(actions); (* NOWARN *)
          obliqClauseList :=
              MetaParser.NewClauseList(actions, "obliq.gr",
                                       TextRd.New(Bundle.Get(ObliqBdl.Get(),
                                                             "ObliqGram")));
        END;
        parser := SynParse.New(swr, SynParse.NewEnv());
        MetaParser.AddClauseList(obliqClauseList, parser);
      EXCEPT
      | SynParse.Fail, SynScan.Fail, SynScan.NoReader =>
        Process.Crash("Failed trying to parse Obliq grammar.");
      END;
    END;
    SynScan.SetPrompt(parser.Scanner(), "- ", "  ");
    RETURN parser;
  END New;

  PROCEDURE ReadFrom(p: T; rdName: TEXT; rd: Rd.T; closeRd: BOOLEAN;
    generateEOF: BOOLEAN := TRUE) =
  BEGIN
    SynScan.PushInput(p.Scanner(), rdName, rd, closeRd, generateEOF);
  END ReadFrom;

  PROCEDURE ParseTerm(p: SynParse.T): Obliq.Term RAISES {Error, Eof} =
  BEGIN
      TRY
        TYPECASE p.ReadNonTerminal("phrase") OF
        | ObTree.PhraseTerm(node) =>
          RETURN node.term;
        ELSE
          SynParse.Fault(p,
            "ObliqParser.ParseTerm: parsed a phrase that is not a term");
          <*ASSERT FALSE*>
        END;
      EXCEPT
      | SynScan.NoReader =>
          RAISE Eof;
      | SynParse.Fail, SynScan.Fail =>
          Obliq.RaiseError("Static Error");
          <*ASSERT FALSE*>
      END;
  END ParseTerm;

  PROCEDURE ParsePhrase(p: SynParse.T): Obliq.Phrase RAISES {Error, Eof} =
  BEGIN
      TRY
        RETURN p.ReadNonTerminal("phrase");
      EXCEPT
      | SynScan.NoReader =>
          RAISE Eof;
      | SynParse.Fail, SynScan.Fail =>
          Obliq.RaiseError("Static Error");
          <*ASSERT FALSE*>
      END;
  END ParsePhrase;

  PROCEDURE EvalPhrase(p: SynParse.T; phrase: Phrase; VAR (*in-out*) env: Env;
    loc: Location:=NIL): Obliq.Val(*or NIL*) RAISES {Error, Exception} =
  VAR val: ObValue.Val;
  BEGIN
    IF loc=NIL THEN loc:=SourceLocation("Obliq.EvalPhrase") END;
    val := NIL;
    TRY
      TYPECASE phrase OF
      | NULL =>
      | ObFrame.Quit => Process.Exit();
      | ObFrame.Load(node) =>
	    ObFrame.LoadFile(p.Scanner(), node.name);
      | ObFrame.Import(node) =>
	    ObFrame.ImportFrame(p.Scanner(), node.name, env);
      | ObFrame.Module(node) =>
	    ObFrame.ModuleFrame(p.Scanner(), node.name, node.for,
	      node.imports, env);
      | ObFrame.AddHelp(node) =>
	    ObFrame.AddHelpFrame(node.name, node.sort, node.short,
                                 node.long, env);
      | ObFrame.EndModule(node) =>
	    ObFrame.ModuleEnd(p.Scanner(), node.ideList);
      | ObFrame.Establish(node) =>
	    env := ObFrame.EstablishFrame(node.name, node.for, env);
      | ObFrame.Save(node) =>
	    env := ObFrame.SaveFrame(node.name, node.name, env);
      | ObFrame.Delete(node) =>
	    env := ObFrame.DeleteFrame(node.name, env);
      | ObFrame.Qualify(node) =>
	    env := ObFrame.QualifyFrame(env, node.ideList);
      | ObTree.PhraseCommand,
        ObTree.PhraseTerm =>
          val := Obliq.EvalPhrase(phrase, (*in-out*) env, loc);
      ELSE
        Obliq.RaiseError("Static Error, unknown phrase", loc);
      END;
      RETURN val;
    EXCEPT
    | ObErr.Fail =>
        Obliq.RaiseError("Static Error", loc);
        <*ASSERT FALSE*>
    END;
  END EvalPhrase;

  PROCEDURE SourceLocation(where: TEXT): SynLocation.T =
  BEGIN
    RETURN
      SynLocation.NewLineLocation(
        SynLocation.Info{fileName:=where, line:=0, lineChar:=0, char:=0});
  END SourceLocation;

BEGIN
END ObliqParser.