blaise_pascal.atg 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. COMPILER Blaise
  2. IGNORE CASE
  3. (* Blaise Pascal grammar for Coco/R, derived from
  4. * Blaise/blaise-master/docs/grammar.ebnf (Phases 1-9a) and validated
  5. * against the blaise v0.14.0-SNAPSHOT oracle binary.
  6. *
  7. * Syntax-only validator grammar: no semantic actions. Deliberate
  8. * divergences from the reference, all in the lenient (accept-more)
  9. * direction except where noted:
  10. * - TEXT_BLOCK literals (''' ... ''') are rewritten to plain strings
  11. * by a length-preserving pre-scan filter (TextFilter): the merged
  12. * Coco/R scanner DFA cannot tell '''-open apart from string-escape,
  13. * so the grammar never sees triple quotes. Classic strings may span
  14. * lines (superset, harmless) so filtered blocks lex as one string;
  15. * positions are preserved exactly.
  16. * - {$...} directives are skipped as comments, including $IFDEF bodies
  17. * (no conditional-compilation processing).
  18. * - "property", "read", "write", "operator", "reference", "object",
  19. * "weak", "message", "on", "Supports" stay identifiers (all
  20. * oracle-proven usable as such); "property" declarations, accessors
  21. * and "on"-clauses ("on E do", "on V: E do") are recognized
  22. * structurally by position.
  23. * - Visibility words (private/protected/public/published/strict),
  24. * "inherited", "out", "packed", "break", "continue" are reserved
  25. * (all oracle-proven); directive words double as ordinary names via
  26. * NIdent in every member/routine/type/const/var/param/enum/selector
  27. * position (only structural slots keep the bare keywords).
  28. * - "static" is an identifier: bare "static" in member position is a
  29. * section qualifier, "static var" flows into VarSection, everything
  30. * else flows into the normal member loop. A member named "static"
  31. * followed by "procedure" etc. would misparse (vanishingly rare).
  32. * - Explicit generic free-function calls (f<T>(x)) need two-token
  33. * lookahead the reference parser has but Coco/R lacks (documented
  34. * gap, zero corpus use); generic DECLARATIONS are fully supported,
  35. * and value-position "<"-brackets take lenient generic-argument
  36. * expressions so dotted comparisons (Obj.F < X) never misparse
  37. * (the tree may differ, the verdict never does).
  38. * - Arrow lambdas use "->" (the EBNF ARROW token is never defined, but
  39. * the whole corpus uses "->"; "=>" never appears in code). Bare and
  40. * parenthesised untyped params are supported; typed-param lambdas
  41. * ((x: T) -> ...) are a documented gap (zero corpus use).
  42. * - AsmBlock bodies are opaque assembly text and cannot be tokenised;
  43. * routines with asm bodies are a documented gap (RTL files only).
  44. * - "or" (additive level), "in" (comparison level), unary minus,
  45. * character literals (#nn, adjacently concatenated) and float
  46. * literals are accepted in runtime expressions although the EBNF
  47. * expression section omits them — the oracle binary accepts all of
  48. * them, so the EBNF is incomplete there, not the validator. String
  49. * concatenation with named constants ('a' + B) folds into the same
  50. * arithmetic chain (superset, harmless).
  51. * - "break", "continue", "case..of..(else)..end" and "repeat..until"
  52. * exist although the EBNF statement section omits them (all oracle-
  53. * proven, all heavily used in the corpus). Case labels reuse the set-
  54. * element shape (single values and ranges). Empty statements (a bare
  55. * ";" or comment-only branches) are accepted per the EBNF Stmt.
  56. * - A "class of T" metaclass type, "class;" / "class(X);" forward
  57. * forms, pointer-deref with selectors (P^.F), call-then-select
  58. * (F(X).Y), parenthesised-lvalue assignment ((E).F := v) and
  59. * "[Weak]"/"[TestCase(...)]" attribute prefixes are all accepted
  60. * (oracle-proven or corpus-proven).
  61. * - A "static" routine implementation following a type/const/var
  62. * section in the same block is folded into that section's last
  63. * declaration (single-token decision on "=" vs routine keywords);
  64. * otherwise the section loop would choke on the identifier.
  65. * - Conditional-compilation fragments ({$IFDEF}/{$ELSE}/{$ENDIF}
  66. * skipped as comments) that leave complete sequential constructs —
  67. * repeated uses-groups, stray begin..end blocks at declaration
  68. * level — are accepted (superset, harmless); truly split constructs
  69. * may still error (rare).
  70. * - A routine body needs no trailing ";" before the enclosing "end"
  71. * (oracle-accepted although the EBNF requires one).
  72. * - Declaration sections (type/const/var/threadvar/routines) may appear
  73. * in any order and repeat, in programs, units and routine bodies —
  74. * the oracle accepts const-before-type etc. although the EBNF shows
  75. * type-first only.
  76. * - Statement lists tolerate a missing ";" before the closing keyword
  77. * ("begin S end", "S; else/end" in case/except) although the EBNF shape
  78. * does not — the oracle accepts all of them. The ";"-led loops use a
  79. * progress-guaranteed [";" [X]] shape (never nullable members, which
  80. * would hang the generated parser).
  81. * - Stray/leading semicolons (";", "S1;; S2") are rejected although
  82. * the EBNF empty-Stmt accepts them (typo-grade code only).
  83. * - Bare identifier statements ("Foo;") are rejected; the oracle
  84. * requires "()" for parameterless calls (explicit oracle message).
  85. * - "inherited" requires a method name with mandatory parens (oracle).
  86. * - Method-call parens are optional (lenient); "procedure of Foo"
  87. * (only "object" is valid) and similar are accepted (lenient).
  88. * - Method bodies use a RoutineBlock whose members never start with a
  89. * bare identifier (nested routines are keyword-led); otherwise the
  90. * optional body would spuriously swallow a following member ("static",
  91. * fields, ...) and hang-or-error. In-class members use an even tighter
  92. * ClassBodyBlock (no nested routines: a bodiless in-class method never
  93. * absorbs the next member; nested-in-method is a documented rare gap).
  94. * Full Blocks stay everywhere a block is required, not optional.
  95. * - Method directives are a closed vocabulary (virtual/override/
  96. * abstract/reintroduce/forward/overload/varargs/cdecl/stdcall/pascal/
  97. * safecall/inline/final/sealed/dynamic/deprecated/external). A bare
  98. * identifier is NOT a directive, so a following member (notably
  99. * "static ...") is never swallowed. Directive words that occur as
  100. * unit/member names ("assembler", "nostackframe", "register") stay
  101. * identifiers; "overload"/"varargs" are also legal unit-name parts.
  102. * - MethodSignature, TypeRef and StrLit are used but never defined in
  103. * the reference; they are read as routine-signature shape, a type
  104. * name, and a string literal. Dotted unit names may repeat in
  105. * semicolon-separated groups (conditional-compilation fragments)
  106. * and use directive-tolerant components.
  107. * - Leading-underscore identifiers (_Foo) are accepted (used by the
  108. * RTL although the EBNF IDENT cannot lex them).
  109. * - The quote-content set excludes CHR(0): otherwise an unterminated
  110. * string at EOF spins the generated scanner forever
  111. * (pre-existing Coco/R quirk: NUL matches ANY-derived sets).
  112. * - Dotted names are accepted in const requests, array indices and
  113. * set element types where the EBNF allows bare idents only
  114. * (oracle rejects them there; lenient superset, harmless).
  115. *)
  116. CHARACTERS
  117. eol = CHR(10) .
  118. nul = CHR(0) .
  119. letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
  120. digit = "0123456789" .
  121. hexDigit = digit + "ABCDEF" .
  122. octDigit = "01234567" .
  123. binDigit = "01" .
  124. noQuote = ANY - "'" - eol - nul .
  125. IGNORE CHR(9) .. CHR(13)
  126. COMMENTS FROM "(*" TO "*)" NESTED
  127. COMMENTS FROM "{" TO "}"
  128. COMMENTS FROM "//" TO eol
  129. COMMENTS FROM "{$" TO "}"
  130. TOKENS
  131. ident = ( letter | "_" ) { letter | digit | "_" } .
  132. integer = digit { ["_"] digit } | digit { ["_"] digit } CONTEXT ( ".." )
  133. | "$" hexDigit { ["_"] hexDigit }
  134. | "&" octDigit { ["_"] octDigit }
  135. | "%" binDigit { ["_"] binDigit } .
  136. real = digit { ["_"] digit } "." digit { ["_"] digit }
  137. [ "E" ["+" | "-"] digit { ["_"] digit } ]
  138. | digit { ["_"] digit } "E" ["+" | "-"] digit { ["_"] digit } .
  139. string = "'" { noQuote | eol | "''" } "'" .
  140. PRODUCTIONS
  141. Blaise = program | Unit .
  142. program = "program" ident ";" [ UsesClause ] Block "." .
  143. Unit = "unit" NameComp { "." NameComp } ";" InterfaceSection
  144. ImplementationSection [ InitializationSection ]
  145. [ FinalizationSection ] "end" "." .
  146. InterfaceSection = "interface" [ UsesClause ]
  147. { TypeSection | ConstSection | VarSection
  148. | ThreadVarSection | MethodSig | CompoundStmt [";"] } .
  149. MethodSig = MethodHead { MethodDirective ";" } .
  150. ImplementationSection = "implementation" [ UsesClause ]
  151. { TypeSection | ConstSection | VarSection
  152. | ThreadVarSection | StandaloneDecl | CompoundStmt [";"] } .
  153. InitializationSection = "initialization" StmtList .
  154. FinalizationSection = "finalization" StmtList .
  155. UsesClause = "uses" UsesGroup { UsesGroup } .
  156. UsesGroup = UnitName { "," UnitName } ";" .
  157. UnitName = NameComp { "." NameComp } .
  158. NameComp = ident | "overload" | "varargs" | "external"
  159. | "set" | "threadvar"
  160. | "and" | "or" | "xor" | "div" | "mod" | "not"
  161. | "shl" | "shr" | "sar" | "in" | "is" | "as" .
  162. NIdent = ident | "virtual" | "override" | "abstract" | "reintroduce"
  163. | "forward" | "overload" | "varargs" | "cdecl" | "stdcall"
  164. | "pascal" | "safecall" | "inline" | "final" | "sealed"
  165. | "dynamic" | "deprecated" | "external" | "default" .
  166. Block = { TypeSection | ConstSection | VarSection
  167. | ThreadVarSection | StandaloneDecl }
  168. "begin" StmtList "end" .
  169. RoutineBlock = { TypeSection | ConstSection | VarSection
  170. | ThreadVarSection | MethodHead MethodTail }
  171. "begin" StmtList "end" .
  172. ClassBodyBlock = { TypeSection | ConstSection | VarSection
  173. | ThreadVarSection }
  174. "begin" StmtList "end" .
  175. TypeSection = "type" TypeDecl { TypeDecl } .
  176. TypeDecl = [ BracketAttr ] NIdent [ "<" TypeParamList ">" ]
  177. ( "=" TypeDef ";" | MethodHead MethodTail | PropertyRest ) .
  178. TypeParamList = ident { "," ident } .
  179. TypeDef = RecordDef | ClassDef | InterfaceDef | EnumDef
  180. | ProceduralType | IntSubrange | TypeName .
  181. IntSubrange = [ "-" ] integer ".." [ "-" ] integer .
  182. RecordDef = [ "packed" ] "record"
  183. { VisibilitySection | ConstSection | MemberField | AttrMember
  184. | MethodDecl | ClassOperatorDecl | VarSection | CompoundStmt [";"] }
  185. "end" .
  186. ClassDef = "class" ( "(" GenericName { "," GenericName } ")" ClassBody
  187. | "of" TypeName
  188. | ClassBody ) .
  189. ClassBody = [ { VisibilitySection | ConstSection | MemberField | AttrMember
  190. | MethodDecl | ClassOperatorDecl | VarSection | CompoundStmt [";"] } ]
  191. [ "end" ] .
  192. VisibilitySection = [ "strict" ] ( "private" | "protected" )
  193. | ( "public" | "published" ) .
  194. GenericName = ident [ "<" TypeArgList ">" ] .
  195. TypeArgList = GenericName { "," GenericName } .
  196. InterfaceDef = "interface" [ "(" ident ")" ]
  197. { MethodSig | PropertyDecl } "end" .
  198. MemberField = IdentList [ ":" TypeName ";" | PropertyRest ] .
  199. AttrMember = BracketAttr { BracketAttr }
  200. ( MethodHead MethodTail
  201. | "class" ident [ "(" ParamList ")" ] ":" TypeName ";"
  202. { MethodDirective ";" } [ ClassBodyBlock [ ";" ] ]
  203. | IdentList ( ":" TypeName ";" | PropertyRest ) ) .
  204. PropertyRest = NIdent [ "[" NIdent ":" TypeName "]" ] ":" TypeName
  205. [ NIdent [ NIdent [ NIdent [ NIdent ] ] ] ] ";"
  206. [ "default" ";" ] .
  207. BracketAttr = "[" AttrItem { [ "," ] AttrItem } "]" .
  208. AttrItem = ident [ "(" [ ArgList ] ")" ] .
  209. IdentList = NIdent { "," NIdent } .
  210. ClassOperatorDecl = "class" ident
  211. [ "(" ParamList ")" ] ":" TypeName ";"
  212. { MethodDirective ";" } [ ClassBodyBlock [ ";" ] ] .
  213. MethodDecl = MethodHead MethodTailClass .
  214. MethodTailClass = { MethodDirective ";" } [ ClassBodyBlock [ ";" ] ] .
  215. MethodHead = ( "procedure" | "function" | "constructor" | "destructor" ) NIdent
  216. { "<" TypeParamList ">" | "." NIdent }
  217. [ "(" [ ParamList ] ")" ] [ ":" TypeName ] ";" .
  218. MethodTail = { NonBodylessDir ";" }
  219. [ BodylessDir ";" | RoutineBlock [ ";" ] ] .
  220. NonBodylessDir = "virtual" | "override" | "reintroduce"
  221. | "overload" | "varargs"
  222. | "cdecl" | "stdcall" | "pascal" | "safecall"
  223. | "inline" | "final" | "sealed" | "dynamic" | "deprecated" .
  224. BodylessDir = "forward" | "abstract" | ExternalDirective .
  225. MethodDirective = "virtual" | "override" | "abstract" | "reintroduce"
  226. | "forward" | "overload" | "varargs"
  227. | "cdecl" | "stdcall" | "pascal" | "safecall"
  228. | "inline" | "final" | "sealed" | "dynamic" | "deprecated"
  229. | ExternalDirective .
  230. ExternalDirective = "external" [ string ] [ ident string ] .
  231. StandaloneDecl = ClassOperatorDecl | MethodHead MethodTail | ident .
  232. PropertyDecl = [ BracketAttr ] NIdent PropertyRest .
  233. ParamList = ParamGroup { ";" ParamGroup } .
  234. ParamGroup = [ "var" | "out" | "const" ] IdentList ":" ParamType
  235. [ "=" DefaultValue ] .
  236. ParamType = "array" "of" ( "const" | TypeName )
  237. | TypeName .
  238. DefaultValue = ConstArithExpr | "nil" .
  239. ConstSection = "const" ConstDecl { ConstDecl } .
  240. ConstDecl = NIdent [ ":" ConstTypeAnnotation ]
  241. ( "=" ConstRhs ";" | MethodHead MethodTail | PropertyRest ) .
  242. ConstTypeAnnotation = TypeName .
  243. ConstRhs = "(" ConstRhsElem { "," ConstRhsElem } ")"
  244. | ConstArithExpr
  245. | "[" [ ident { "," ident } ] "]" .
  246. ConstRhsElem = "(" ConstRhsElem { "," ConstRhsElem } ")"
  247. | ConstArithExpr .
  248. ConstArithExpr = ConstArithTerm { ( "+" | "-" | "or" | "xor" ) ConstArithTerm } .
  249. ConstArithTerm = ConstArithFactor
  250. { ( "*" | "/" | "div" | "mod" | "and" | "shl" | "shr" ) ConstArithFactor } .
  251. ConstArithFactor = integer | real | StrChain
  252. | NIdent { Selector } [ "(" [ ArgList ] ")" ]
  253. | "-" ConstArithFactor | "(" ConstArithExpr ")" .
  254. VarSection = "var" VarDecl { VarDecl } .
  255. ThreadVarSection = "threadvar" VarDecl { VarDecl } .
  256. VarDecl = [ BracketAttr ] IdentList
  257. ( ":" TypeName [ "=" ConstValue ] ";"
  258. | MethodHead MethodTail | PropertyRest ) .
  259. ConstValue = ConstRhs | "nil" .
  260. TypeName = "array" [ "[" ArrayIndexSpec "]" ] "of" TypeName
  261. | SetType
  262. | "^" TypeName
  263. | ident { "." NIdent | "<" TypeArgList ">" }
  264. [ ".." ident ] [ "to" ProcTypeCore ] .
  265. ArrayIndexSpec = ConstArithExpr
  266. [ ".." ConstArithExpr
  267. { "," ConstArithExpr ".." ConstArithExpr } ] .
  268. EnumDef = "(" EnumMember { "," EnumMember } ")" .
  269. EnumMember = NIdent [ "=" [ "-" ] integer ] .
  270. SetType = "set" "of"
  271. ( NIdent { "." NIdent } [ ".." ConstArithExpr ]
  272. | EnumDef
  273. | Subrange ) .
  274. Subrange = ConstArithExpr ".." ConstArithExpr .
  275. ProcTypeCore = ( "function" [ "(" [ ParamList ] ")" ] ":" TypeName [ "of" ident ]
  276. | "procedure" [ "(" [ ParamList ] ")" ] [ "of" ident ] ) .
  277. ProceduralType = ProcTypeCore .
  278. StmtList = [ Stmt { ";" [ Stmt ] } ] .
  279. Stmt = [ IfStmt | WhileStmt | ForStmt | TryStmt | CaseStmt | RepeatStmt
  280. | RaiseStmt | ExitStmt | CompoundStmt | BlockVarDeclStmt
  281. | "break" | "continue"
  282. | "inherited" ident "(" [ ArgList ] ")"
  283. | NIdent IdentStmtTail ] .
  284. IdentStmtTail = StmtTail
  285. | NIdent [ ":" NIdent { "." NIdent | "<" TypeArgList ">" } ]
  286. "do" Stmt .
  287. StmtTail = ":=" Expr
  288. | "^" { Selector } [ ":=" Expr ]
  289. | PostfixBody [ ":=" Expr ] .
  290. PostfixBody = ( Selector | "<" GenArgs [ ">" ] | "(" [ ArgList ] ")" ) Postfix .
  291. Postfix = { Selector | "<" GenArgs [ ">" ] | "(" [ ArgList ] ")" } .
  292. GenArgs = Additive { "," Additive } .
  293. Selector = "." NIdent [ "(" [ ArgList ] ")" ]
  294. | "[" Expr { "," Expr } "]" .
  295. IfStmt = "if" Expr "then" Stmt [ "else" Stmt ] .
  296. WhileStmt = "while" Expr "do" Stmt .
  297. ForStmt = "for" NIdent
  298. ( ":=" Expr ( "to" | "downto" ) Expr | "in" Expr )
  299. "do" Stmt .
  300. TryStmt = "try" StmtList ( "finally" StmtList | "except" ExceptBody ) "end" .
  301. CaseStmt = "case" Expr "of"
  302. [ OneCase { ";" [ OneCase ] } ] [ "else" StmtList ] "end" .
  303. OneCase = SetElement { "," SetElement } ":" Stmt .
  304. RepeatStmt = "repeat" StmtList "until" Expr .
  305. ExceptBody = StmtList [ "else" StmtList ] .
  306. RaiseStmt = "raise" [ Expr ] .
  307. ExitStmt = "exit" [ "(" Expr ")" ] .
  308. CompoundStmt = "begin" StmtList "end" .
  309. BlockVarDeclStmt = "var" NIdent ":" TypeName [ ":=" Expr ] .
  310. ArgList = Expr { "," Expr } .
  311. Expr = Comparison [ ( "is" | "as" ) ident ] .
  312. Comparison = Additive
  313. [ ( "=" | "<>" | "<" | ">" | "<=" | ">=" | "in" ) Additive ] .
  314. Additive = Term { ( "+" | "-" | "or" ) Term } .
  315. Term = Factor
  316. { ( "*" | "/" | "div" | "mod" | "and" | "xor"
  317. | "shl" | "shr" | "sar" ) Factor } .
  318. Factor = ( integer | real | StrChain | "nil"
  319. | "[" [ SetElement { "," SetElement } ] "]"
  320. | AnonMethod
  321. | "@" Factor
  322. | "not" Factor
  323. | "-" Factor
  324. | "inherited" ident "(" [ ArgList ] ")"
  325. | NIdent Postfix [ "->" LambdaBody ]
  326. | "(" [ Expr { "," Expr } ] ")" { Selector } [ "->" LambdaBody ]
  327. ) { "^" { Selector } } .
  328. CharLit = "#" integer { "#" integer } .
  329. SetElement = Expr [ ".." Expr ] .
  330. StrChain = ( string | CharLit ) { ( string | CharLit ) } .
  331. LambdaBody = Expr | Block .
  332. AnonMethod = ( "procedure" | "function" )
  333. [ BracketAttr ]
  334. [ "(" [ ParamList ] ")" ] [ ":" TypeName ]
  335. Block .
  336. END Blaise.