瀏覽代碼

Blaise validator pilot (grammar, build, tests)

Eric Streit 4 天之前
父節點
當前提交
901e1e4366
共有 4 個文件被更改,包括 190 次插入 和 0 次删除
  1. 43 0
      grammars/Blaise/README.md
  2. 95 0
      grammars/Blaise/blaise_pascal.atg
  3. 24 0
      grammars/Blaise/build.sh
  4. 28 0
      grammars/Blaise/tests/deep.Mod

+ 43 - 0
grammars/Blaise/README.md

@@ -0,0 +1,43 @@
+# Blaise validator pilot
+
+`blaise_pascal.atg` is byte-identical to the classic-Oberon grammar
+(`Grammars/Oberon-grammar/original_oberon.atg`) apart from its tag
+line — despite the name, it describes Oberon, not Pascal. It needed
+the same 4 fixes as the Oberon-07 pilot to build with Coco/R V1.53
+(`CR`) and GNU Modula-2 (`gm2 -fiso`), all diagnosed against `ulmo`
+(Ulm Oberon) as oracle:
+
+1. `statement`: `assignment | ProcedureCall` factored into
+   `AssignmentOrProcedureCall` (duplicate `CASE` labels — uncompilable).
+2. `designator`: dropped `"(" qualident ")"` (hijacked call parens).
+3. `qualident`: `[ ident "." ] ident` rewritten as
+   `ident { "." ident }` (optional-prefix lookahead trap).
+4. `real` requires post-dot digits + `CONTEXT ("..")` on integers
+   (the `2..3` lexer trap).
+
+(No `FOR` production added: like Oberon-07, `ulmo` rejects `FOR`, so
+grammar and oracle agree.)
+
+Two benign LL(1) warnings remain. Note: `ulmo`'s backend aborts with
+an `OberonAMD64.Pass2` assertion on every successful parse in this
+environment, so it serves as a frontend-only oracle (its `**` error
+lines); `voc` independently compiles `tests/deep.Mod` clean.
+
+## Build
+
+```sh
+./build.sh        # -> build/Blaise (build/ is git-ignored)
+```
+
+Needs `CR` (Coco/R), `gm2 -fiso`, the `parser.frm`/`scanner.frm`
+frames and `FileIO.def/.mod` — all resolved from the environment with
+sensible defaults (`CRFRAMES`, `M2LIB`, `CR`, `GM2`).
+
+## Differential results (Blaise vs `ulmo`)
+
+19 accept probes + `tests/deep.Mod` (records, pointers, nested
+recursion, CASE ranges, hex/reals/strings): **0 false positives**.
+9 broken mutants: **0 missed**, positions close. `voc` quirks do not
+apply here (`ulmo` is the oracle); the one systematic divergence is
+`WITH` bare fields, which `ulmo` rejects while the validator accepts
+(lenient direction, same as the Oberon-07 pilot).

+ 95 - 0
grammars/Blaise/blaise_pascal.atg

@@ -0,0 +1,95 @@
+(* Tags: BLAISE, BLAISEPASCALE, BLA *)
+(* Tags: ORIGINAL, OISOberon, Classic, ETHOberon *)
+COMPILER Oberon
+(* A grammar for Oberon *)
+
+CHARACTERS
+  eol      = CHR(13) .
+  letter   = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
+  digit    = "0123456789" .
+  hexDigit = digit + "ABCDEF" .
+  noQuote  = ANY - '"' - eol  .
+
+IGNORE  CHR(9) .. CHR(13)
+
+COMMENTS
+  FROM "(*" TO "*)" NESTED
+
+TOKENS
+  ident   =  letter { letter | digit } .
+  integer  =  digit { digit } | digit { digit } CONTEXT ( ".." )
+           | digit { hexDigit } "H" .
+  real  =  digit { digit } "." digit { digit }
+           [ ("E" | "D") [ "+" | "-" ] digit { digit } ] .
+  CharConstant = digit { hexDigit } "X" .
+  string  =  '"' { noQuote } '"' .
+
+PRODUCTIONS
+  Oberon           =  module .
+  number           =  integer | real .
+  identdef         =  ident [ "*" ] .
+  qualident        =  ident { "." ident } .
+  ConstantDeclaration  =  identdef "=" ConstExpression .
+  ConstExpression  =  expression .
+  TypeDeclaration  =  identdef "=" type .
+  type             =  qualident | ArrayType | RecordType | PointerType | ProcedureType .
+  ArrayType        =  "ARRAY" length { "," length } "OF" type .
+  length           =  ConstExpression .
+  RecordType       =  "RECORD" [ "(" BaseType ")" ] FieldListSequence "END" .
+  BaseType         =  qualident .
+  FieldListSequence  =  FieldList { ";" FieldList } .
+  FieldList        =  [ IdentList ":" type ] .
+  IdentList        =  identdef { "," identdef } .
+  PointerType      =  "POINTER" "TO" type .
+  ProcedureType    =  "PROCEDURE" [ FormalParameters ] .
+  VariableDeclaration  =  IdentList ":" type .
+  designator       =  qualident { "." ident | "[" ExpList "]" | "^"  } .
+  ExpList          =  expression { "," expression } .
+  expression       =  SimpleExpression [ relation SimpleExpression ] .
+  relation         =  "=" | "#" | "<" | "<=" | ">" | ">=" | "IN" | "IS" .
+  SimpleExpression =  [ "+" | "-" ] term { AddOperator term } .
+  AddOperator      =  "+" | "-" | "OR" .
+  term             =  factor { MulOperator factor } .
+  MulOperator      =  "*" | "/" | "DIV" | "MOD" | "&" .
+  factor           =  number | CharConstant | string | "NIL" | set
+                      | designator [ ActualParameters ]
+                      | "(" expression ")" | "~" factor .
+  set              =  "{" [ element { "," element } ] "}" .
+  element          =  expression [ ".." expression ] .
+  ActualParameters =  "(" [ ExpList ] ")" .
+  statement        =  [ AssignmentOrProcedureCall | IfStatement |
+                        CaseStatement | WhileStatement | RepeatStatement |
+                        LoopStatement | WithStatement | "EXIT" |
+                        "RETURN" [ expression ] ] .
+  AssignmentOrProcedureCall = designator ( ":=" expression | [ ActualParameters ] ) .
+  StatementSequence =  statement { ";" statement } .
+  IfStatement      =  "IF" expression "THEN" StatementSequence
+                     { "ELSIF" expression "THEN" StatementSequence }
+                     [ "ELSE" StatementSequence ] "END" .
+  CaseStatement    =  "CASE" expression "OF" case { "|" case }
+                     [ "ELSE" StatementSequence ] "END" .
+  case             =  [ CaseLabelList ":" StatementSequence ] .
+  CaseLabelList    =  CaseLabels { "," CaseLabels } .
+  CaseLabels       =  ConstExpression [ ".." ConstExpression ] .
+  WhileStatement   =  "WHILE" expression "DO" StatementSequence "END" .
+  RepeatStatement  =  "REPEAT" StatementSequence "UNTIL" expression .
+  LoopStatement    =  "LOOP" StatementSequence "END" .
+  WithStatement    =  "WITH" qualident ":" qualident "DO" StatementSequence "END" .
+  ProcedureDeclaration  =  ProcedureHeading ";" ProcedureBody ident .
+  ProcedureHeading =  "PROCEDURE" [ "*" ] identdef [ FormalParameters ] .
+  ProcedureBody    =  DeclarationSequence [ "BEGIN" StatementSequence ] "END" .
+  ForwardDeclaration  =  "PROCEDURE" "^" ident [ "*" ] [ FormalParameters ] .
+  DeclarationSequence  =  {   "CONST" { ConstantDeclaration ";" }
+                            | "TYPE"  { TypeDeclaration ";" }
+                            | "VAR"   { VariableDeclaration ";" } }
+                          {   ProcedureDeclaration ";"
+                            | ForwardDeclaration ";" } .
+  FormalParameters =  "(" [ FPSection { ";" FPSection } ] ")" [ ":" qualident ] .
+  FPSection        =  [ "VAR" ] ident { "," ident } ":" FormalType .
+  FormalType       =  { "ARRAY" "OF" } (qualident | ProcedureType) .
+  ImportList       =  "IMPORT" import { "," import } ";" .
+  import           =  ident [ ":=" ident ] .
+  module           =  "MODULE" ident ";"
+                      [ ImportList ] DeclarationSequence
+                      [ "BEGIN" StatementSequence ] "END" ident "." .
+END Oberon.

+ 24 - 0
grammars/Blaise/build.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+# Build the Blaise/classic-Oberon syntax validator from blaise_pascal.atg.
+# Needs: CR (Coco/R V1.53), gm2 -fiso, parser/scanner frames, FileIO.
+set -e
+CR="${CR:-/home/eric/Projets/Projets-Modula2/MyWork/CocoGm2/CR}"
+GM2="${GM2:-/home/eric/bin/Modula2/Gm2/bin/gm2}"
+FRAMES="${CRFRAMES:-/home/eric/Projets/Projets-Modula2/MyWork/Theia/GNU-grammar/build}"
+M2LIB="${M2LIB:-/home/eric/Projets/Projets-Modula2/MyWork/Theia/GNU-grammar/build}"
+HERE="$(dirname "$0")"
+B="$HERE/build"
+rm -rf "$B"
+mkdir -p "$B"
+cp "$HERE/blaise_pascal.atg" "$B/"
+cp "$M2LIB/FileIO.def" "$M2LIB/FileIO.mod" "$B/"
+cd "$B"
+echo "=== CR ==="; CRFRAMES="$FRAMES" "$CR" -m -C blaise_pascal.atg
+echo "=== compile ==="
+for m in FileIO OberonS OberonP; do "$GM2" -fiso -I . -c "$m.mod"; done
+echo "=== link ==="
+"$GM2" -fiso -I . -o Blaise FileIO.o OberonS.o OberonP.o Oberon.mod
+echo "=== smoke ==="
+printf 'MODULE Hello;\nIMPORT Out;\nBEGIN\n  Out.String("hi");\n  Out.Ln;\nEND Hello.\n' > Hello.Mod
+./Blaise Hello.Mod
+rm -f Hello.Mod Hello.LST

+ 28 - 0
grammars/Blaise/tests/deep.Mod

@@ -0,0 +1,28 @@
+MODULE Deep;
+IMPORT Out;
+CONST N = 10;
+TYPE
+  Point = RECORD x, y: INTEGER END;
+  Node = POINTER TO NodeDesc;
+  NodeDesc = RECORD key: INTEGER; left, right: Node END;
+VAR
+  pt: Point;
+  n: Node;
+  i: INTEGER;
+PROCEDURE Walk(t: Node);
+BEGIN
+  IF t # NIL THEN Walk(t.left); Walk(t.right) END
+END Walk;
+BEGIN
+  NEW(n);
+  n.key := 5; n.left := NIL;
+  pt.x := 1; pt.y := 2;
+  WHILE i < N DO INC(i) END;
+  CASE i OF
+    1..3: Out.Int(i, 0)
+    | 4, 5: Out.Char("x")
+  ELSE
+    Out.Ln
+  END;
+  Walk(n)
+END Deep.