FoxParser.Mod 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493
  1. MODULE FoxParser; (** AUTHOR "fof & fn"; PURPOSE "Oberon Compiler: Parser"; **)
  2. (* (c) fof ETH Zurich, 2009 *)
  3. IMPORT Basic := FoxBasic, Scanner := FoxScanner, D := Debugging, SyntaxTree := FoxSyntaxTree, Global := FoxGlobal, Diagnostics, Streams, Strings, StringPool;
  4. CONST
  5. Trace = FALSE;
  6. CascadedWithSupport = TRUE;
  7. (** the parser reflects the following EBNF:
  8. Module = ('module' | 'cellnet' [Flags]) Identifier ['in' Identifier]';'
  9. {ImportList} DeclarationSequence [Body]
  10. 'end' Identifier '.'.
  11. ImportList = 'import' Import { ',' Import } ';'.
  12. Import = Identifier [':=' Identifier] ['in' Identifier].
  13. DeclarationSequence = {
  14. 'const' [ConstDeclaration] {';' [ConstDeclaration]}
  15. |'type' [TypeDeclaration] {';' [TypeDeclaration]}
  16. |'var' [VariableDeclaration] {';' [VariableDeclaration]}
  17. | ProcedureDeclaration
  18. | OperatorDeclaration
  19. | ';'
  20. }
  21. Declaration = IdentifierDefinition '=' Expression.
  22. TypeDeclaration = IdentifierDefinition '=' Type.
  23. VariableDeclaration = VariableNameList ':' Type.
  24. VariableNameList = IdentifierDefinition [Flags] [':=' Expression | 'extern' String] {',' IdentifierDefinition [Flags] [':=' Expression | 'extern' String] }.
  25. OperatorDeclaration = 'operator' [Flags] ['-'] String ['*'|'-'] FormalParameters ';'
  26. DeclarationSequence [Body] 'end' String.
  27. ProcedureDeclaration = 'procedure' ['^'|'&'|'~'|'-'|Flags ['-']] IdentifierDefinition [FormalParameters]';'
  28. DeclarationSequence [Body] 'end' Identifier.
  29. Flags = '{' [Identifier ['(' Expression ')'|'=' Expression] {',' Identifier ['(' Expression ')' | '=' Expression ] } ] '}'.
  30. FormalParameters = '(' [ParameterDeclaration {';' ParameterDeclaration}] ')' [':' [Flags] Type].
  31. ParameterDeclaration = ['var'|'const'] Identifier [Flags] ['= Expression] {',' Identifier [Flags] ['= Expression]}':' Type.
  32. PortList = '(' [PortDeclaration {';' PortDeclaration}] ')'.
  33. PortDeclaration = Identifier [Flags] {',' Identifier [Flags]}':' Type.
  34. Type = ArrayType | RecordType | PointerType | ObjectType | CellType | CellnetType | PortType
  35. | ProcedureType | EnumerationType | QualifiedIdentifier.
  36. PortType = 'port' ('in'|'out') ['(' Expression ')']
  37. EnumerationType = 'enum' ['('QualifiedIdentifier')'] IdentifierDefinition ['=' Expression]
  38. {',' IdentifierDefinition ['=' Expression]} 'end'.
  39. ArrayType = 'array' 'of' Type | 'array' Expression {',' Expression} 'of' Type
  40. | 'array' '[' MathArraySize {',' MathArraySize} ']' ['of' Type].
  41. MathArraySize = Expression | '*' | '?'.
  42. RecordType = 'record' [Flags] ['(' QualifiedIdentifier ')'] [VariableDeclaration {';' VariableDeclaration}] 'end'.
  43. PointerType = 'pointer' [Flags] 'to' Type.
  44. CellType = 'cell' [Flags] [PortList] [';'] DeclarationSequence [Body] 'end' [Identifier].
  45. ObjectType = 'object' | 'object' [Flags] ['(' (QualifiedIdentifier | ArrayType) ')'] DeclarationSequence [Body] 'end' [Identifier] .
  46. ProcedureType = 'procedure' [Flags] [FormalParameters].
  47. Body = 'begin' [Flags] StatementSequence ['finally' StatementSequence]
  48. | 'code' Code.
  49. Code = { any \ 'end' \ 'with' } ['with' {('in'|'out') StatementSequence}] .
  50. StatementBlock = [Flags] StatementSequence.
  51. StatementSequence = Statement {';' Statement}.
  52. Statement =
  53. [
  54. Designator [':=' Expression |'!' Expression | '?' Expression | '<<' Expresssion | '>>' Expression]
  55. | 'if' Expression 'then' StatementSequence
  56. {'elsif' Expression 'then' StatementSequence}
  57. ['else' StatementSequence]
  58. 'end'
  59. | 'with' Identifier ':' QualifiedIdentifier 'do' StatementSequence
  60. {['|' Identifier ':'] QualifiedIdentifier 'do' StatementSequence}
  61. [else StatementSequence]
  62. 'end'
  63. | 'case' Expression 'of' ['|'] Case {'|' Case} ['else' StatementSequence] 'end'
  64. | 'while' Expression 'do' StatementSequence 'end'
  65. | 'repeat' StatementSequence 'until' Expression
  66. | 'for' Identifier ':=' Expression 'to' Expression ['by' Expression] 'do'
  67. StatementSequence 'end'
  68. | 'loop' StatementSequence 'end'
  69. | 'exit'
  70. | 'return' [Expression]
  71. | 'await' Expression
  72. | 'begin' StatementBlock 'end'
  73. | 'code' {any} 'end'
  74. ].
  75. Case = RangeExpression {',' RangeExpression} ':' StatementSequence.
  76. Expression = RangeExpression [RelationOp RangeExpression].
  77. RelationOp = '=' | '.=' | '#' | '.#'
  78. | '<' | '.<' | '<=' | '.<=' | '>' | '.>' | '>=' | '.>='
  79. | '??' | '!!' | '<<?' | '>>?'
  80. | 'in' | 'is'
  81. SimpleExpression = ['+'|'-'] Term {AddOp Term}.
  82. AddOp = '+' | '-' | 'or'.
  83. Term = Factor {MulOp Factor}.
  84. MulOp = '*' | '**' | '.*' | '+*' | '/' | '\' | './' | 'div' | 'mod' | '&'.
  85. Factor = Number | Character | String | 'nil' | 'imag' | 'true' | 'false' | Set
  86. | '(' Expression ')' | '~' Factor | Factor '`' | Designator | MathArray.
  87. | 'SIZE' 'OF' Designator | 'ADDRESS' 'OF' Designator
  88. MathArray = '[' Expression {',' Expression} ']'.
  89. Set = '{' [ RangeExpression {',' RangeExpression} ] '}'.
  90. Designator = ('self' | 'result' | Identifier)
  91. {'.' Identifier | '[' IndexList ']' | '(' [ExpressionList] ')' | '^'} [Flags].
  92. RangeExpression = SimpleExpression | [SimpleExpression] '..' [SimpleExpression] ['by' SimpleExpression] | '*'.
  93. IndexList = '?' [',' ExpressionList ] | ExpressionList [',' '?'].
  94. ExpressionList = Expression { ',' Expression }.
  95. IdentifierDefinition = Identifier [ '*' | '-' ].
  96. QualifiedIdentifier = Identifier ['.' Identifier].
  97. Identifier = Letter {Letter | Digit | '_'}.
  98. Letter = 'A' | 'B' | .. | 'Z' | 'a' | 'b' | .. | 'z'.
  99. String = '"' {Character} '"' | "'" {Character} "'".
  100. Number = Integer | Real.
  101. Integer = Digit {Digit} | '0' 'x' {HexDigit} | Digit {HexDigit} 'H' .
  102. Real = Digit {Digit} '.' {Digit} [ScaleFactor].
  103. ScaleFactor = ('E' | 'D') ['+' | '-'] digit {digit}.
  104. HexDigit = Digit | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
  105. Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' .
  106. **)
  107. TYPE
  108. Position*=Scanner.Position;
  109. Parser* = OBJECT
  110. VAR scanner-: Scanner.Scanner;
  111. token-: Scanner.Token;
  112. diagnostics: Diagnostics.Diagnostics;
  113. currentScope: SyntaxTree.Scope;
  114. recentCommentItem: ANY; recentLine: LONGINT;
  115. recentComment: SyntaxTree.Comment;
  116. moduleScope: SyntaxTree.ModuleScope;
  117. error-: BOOLEAN;
  118. Lax-: BOOLEAN;
  119. indent: LONGINT; (* for debugging purposes only *)
  120. hasToken: BOOLEAN;
  121. prevPosition-: Position;
  122. (* conditional compilation *)
  123. CONST Processing = 0; ProcessingElse = 1; Skipping = 2; Ignoring = 3; IgnoringElse = 4;
  124. VAR conditional: WORD;
  125. VAR conditionals: ARRAY 10 OF WORD;
  126. VAR definitions: ARRAY 10 OF Scanner.IdentifierType;
  127. VAR conditionalCount, definitionCount: SIZE;
  128. PROCEDURE S( CONST s: ARRAY OF CHAR ); (* for debugging purposes only *)
  129. VAR i: LONGINT;
  130. BEGIN
  131. D.Ln; INC( indent ); D.Int( indent,1 );
  132. FOR i := 1 TO indent DO D.Str( " " ); END;
  133. D.Str( "start: " ); D.Str( s ); D.Str( " at pos " ); D.Int( token.position.start,1 );
  134. END S;
  135. PROCEDURE E( CONST s: ARRAY OF CHAR ); (* for debugging purposes only *)
  136. VAR i: LONGINT;
  137. BEGIN
  138. D.Ln; D.Int( indent,1 );
  139. FOR i := 1 TO indent DO D.Str( " " ); END;
  140. D.Str( "end : " ); D.Str( s ); D.Str( " at pos " ); D.Int( token.position.start,1 );
  141. DEC(indent);
  142. END E;
  143. PROCEDURE EE( CONST s, t: ARRAY OF CHAR ); (* for debugging purposes only *)
  144. VAR i: LONGINT;
  145. BEGIN
  146. D.Ln; D.Int( indent,1 );
  147. FOR i := 1 TO indent DO D.Str( " " ); END;
  148. D.Str( "end : " ); D.Str( s ); D.Str( " (" ); D.Str( t ); D.Str( ") at pos " );
  149. DEC(indent);
  150. END EE;
  151. (** constructor, init parser with scanner providing input and with diagnostics for error output *)
  152. PROCEDURE & Init*( scanner: Scanner.Scanner; diagnostics: Diagnostics.Diagnostics; CONST definitions: ARRAY OF CHAR );
  153. VAR begin, end: LONGINT (* SIZE! *); definition: ARRAY 32 OF CHAR;
  154. BEGIN
  155. conditional := Processing;
  156. conditionalCount := 0;
  157. definitionCount := 0;
  158. begin := 0;
  159. REPEAT
  160. end := Strings.Find (definitions, begin, ',');
  161. IF end # -1 THEN
  162. Strings.Copy (definitions, begin, end - begin, definition);
  163. begin := end + 1;
  164. ELSE
  165. Strings.Copy (definitions, begin, Strings.Length (definitions) - begin, definition);
  166. END;
  167. IF definition # "" THEN
  168. StringPool.GetIndex (definition, SELF.definitions[definitionCount]);
  169. INC (definitionCount);
  170. END;
  171. UNTIL end = -1;
  172. SELF.scanner := scanner;
  173. SELF.diagnostics := diagnostics;
  174. error := ~GetNextToken(token);
  175. hasToken := TRUE;
  176. IF error THEN Basic.Error(diagnostics, scanner.source^, Basic.invalidPosition, "no input stream") END;
  177. recentCommentItem := NIL; recentComment := NIL;
  178. (* debugging *)
  179. indent := 0;
  180. Lax := FALSE;
  181. END Init;
  182. PROCEDURE Reset*;
  183. BEGIN
  184. error := FALSE;
  185. END Reset;
  186. PROCEDURE SetLax*;
  187. BEGIN
  188. Lax := TRUE;
  189. END SetLax;
  190. (** output error message and / or given code *)
  191. PROCEDURE Error(position: Position; code: LONGINT; CONST message: ARRAY OF CHAR);
  192. BEGIN
  193. Basic.ErrorC(diagnostics, scanner.source^, position, code, message);
  194. error := TRUE
  195. END Error;
  196. (* conditional compilation according to the following syntax *)
  197. (* Block = '#' 'if' Condition 'then' Block { '#' 'elsif' Condition 'then' Block } ['#' 'else' Block] '#' 'end' | any symbol until next new line. *)
  198. PROCEDURE GetNextToken(VAR token: Scanner.Token): BOOLEAN;
  199. VAR line: Streams.Position; end: Scanner.Symbol; startPos, endPos: LONGINT;
  200. BEGIN
  201. LOOP
  202. line := token.position.line;
  203. IF ~scanner.GetNextToken (token) THEN RETURN FALSE END;
  204. IF (token.symbol = Scanner.Unequal) & (token.position.line # line) THEN
  205. IF ~ConditionalStatement (token) THEN RETURN FALSE END;
  206. ELSIF (conditional = Processing) OR (conditional = ProcessingElse) THEN
  207. RETURN TRUE;
  208. ELSIF token.symbol = Scanner.Code THEN
  209. end := scanner.SkipToEndOfCode(startPos, endPos, token);
  210. WHILE end = Scanner.Unequal DO
  211. REPEAT scanner.GetNextCharacter() UNTIL (scanner.ch # Scanner.LF) & (scanner.ch # 0X);
  212. end := scanner.SkipToEndOfCode(startPos, endPos, token);
  213. END;
  214. END;
  215. END;
  216. END GetNextToken;
  217. PROCEDURE ConditionalStatement(VAR token: Scanner.Token): BOOLEAN;
  218. VAR value: BOOLEAN;
  219. (* Factor = Identifier | '~' Factor | '(' Condition ')'. *)
  220. PROCEDURE Factor (VAR value: BOOLEAN): BOOLEAN;
  221. VAR i: SIZE;
  222. BEGIN
  223. IF token.symbol = Scanner.Identifier THEN
  224. value := FALSE; i := 0;
  225. WHILE (i # definitionCount) & ~value DO value := token.identifier = definitions[i]; INC (i) END;
  226. IF ~scanner.GetNextToken (token) THEN RETURN FALSE END;
  227. ELSIF token.symbol = Scanner.Not THEN
  228. IF ~scanner.GetNextToken (token) THEN RETURN FALSE END;
  229. IF ~Factor (value) THEN RETURN FALSE END;
  230. value := ~value;
  231. ELSIF token.symbol = Scanner.LeftParenthesis THEN
  232. IF ~scanner.GetNextToken (token) THEN RETURN FALSE END;
  233. IF ~Condition (value) THEN RETURN FALSE END;
  234. IF token.symbol # Scanner.RightParenthesis THEN Error (token.position, Scanner.RightParenthesis, ""); RETURN FALSE END;
  235. IF ~scanner.GetNextToken (token) THEN RETURN FALSE END;
  236. ELSE
  237. Error (token.position, Scanner.Identifier, ""); RETURN FALSE;
  238. END;
  239. RETURN TRUE;
  240. END Factor;
  241. (* Term = Factor {'&' Factor}. *)
  242. PROCEDURE Term (VAR value: BOOLEAN): BOOLEAN;
  243. VAR next: BOOLEAN;
  244. BEGIN
  245. IF ~Factor (value) THEN RETURN FALSE END;
  246. WHILE token.symbol = Scanner.And DO
  247. IF ~scanner.GetNextToken (token) THEN RETURN FALSE END;
  248. IF ~Factor (next) THEN RETURN FALSE END;
  249. IF ~next THEN value := FALSE END;
  250. END;
  251. RETURN TRUE;
  252. END Term;
  253. (* Condition = Term {'or' Term}. *)
  254. PROCEDURE Condition (VAR value: BOOLEAN): BOOLEAN;
  255. VAR next: BOOLEAN;
  256. BEGIN
  257. IF ~Term (value) THEN RETURN FALSE END;
  258. WHILE token.symbol = Scanner.Or DO
  259. IF ~scanner.GetNextToken (token) THEN RETURN FALSE END;
  260. IF ~Term (next) THEN RETURN FALSE END;
  261. IF next THEN value := TRUE END;
  262. END;
  263. RETURN TRUE;
  264. END Condition;
  265. BEGIN
  266. IF ~scanner.GetNextToken (token) THEN RETURN FALSE END;
  267. IF token.symbol = Scanner.If THEN
  268. IF ~scanner.GetNextToken (token) THEN RETURN FALSE END;
  269. IF ~Condition (value) THEN RETURN FALSE END;
  270. IF token.symbol # Scanner.Then THEN Error (token.position, Scanner.Then, ""); RETURN FALSE END;
  271. conditionals[conditionalCount] := conditional; INC (conditionalCount);
  272. IF (conditional # Processing) & (conditional # ProcessingElse) THEN conditional := Ignoring;
  273. ELSIF value THEN conditional := Processing ELSE conditional := Skipping;
  274. END;
  275. ELSIF token.symbol = Scanner.Elsif THEN
  276. IF ~scanner.GetNextToken (token) THEN RETURN FALSE END;
  277. IF ~Condition (value) THEN RETURN FALSE END;
  278. IF token.symbol # Scanner.Then THEN Error (token.position, Scanner.Then, ""); RETURN FALSE END;
  279. IF (conditional = Processing) & (conditionalCount # 0) OR (conditional = Ignoring) THEN conditional := Ignoring;
  280. ELSIF conditional = Skipping THEN IF value THEN conditional := Processing ELSE conditional := Skipping END;
  281. ELSE Error(token.position,Basic.InvalidCode,"invalid conditional elsif"); RETURN FALSE END;
  282. ELSIF token.symbol = Scanner.Else THEN
  283. IF (conditional = Processing) & (conditionalCount # 0) OR (conditional = Ignoring) THEN conditional := IgnoringElse;
  284. ELSIF conditional = Skipping THEN conditional := ProcessingElse;
  285. ELSE Error(token.position,Basic.InvalidCode,"invalid conditional else"); RETURN FALSE END;
  286. ELSIF token.symbol = Scanner.End THEN
  287. IF conditionalCount # 0 THEN DEC (conditionalCount); conditional := conditionals[conditionalCount];
  288. ELSE Error(token.position,Basic.InvalidCode,"invalid conditional end"); RETURN FALSE END;
  289. ELSE
  290. Error(token.position,Basic.InvalidCode,"invalid conditional statement"); RETURN FALSE;
  291. END;
  292. RETURN TRUE;
  293. END ConditionalStatement;
  294. (** helper procedures interfacing to the scanner **)
  295. PROCEDURE SkipComments(b: BOOLEAN);
  296. VAR comment: SyntaxTree.Comment;
  297. BEGIN
  298. WHILE ~error & (b & (TokenB()= Scanner.Comment) OR ~b & (Symbol() = Scanner.Comment)) DO
  299. comment := SyntaxTree.NewComment(token.position, currentScope, token.string^,token.stringLength);
  300. IF moduleScope # NIL THEN
  301. moduleScope.AddComment(comment);
  302. END;
  303. IF recentComment = NIL THEN
  304. recentComment := comment;
  305. IF token.position.line = recentLine THEN
  306. IF recentCommentItem # NIL THEN
  307. IF (recentCommentItem IS SyntaxTree.Symbol) THEN
  308. IF recentCommentItem(SyntaxTree.Symbol).comment = NIL THEN
  309. recentCommentItem(SyntaxTree.Symbol).SetComment(comment)
  310. END;
  311. ELSIF (recentCommentItem IS SyntaxTree.Statement) THEN
  312. IF recentCommentItem(SyntaxTree.Statement).comment = NIL THEN
  313. recentCommentItem(SyntaxTree.Statement).SetComment(comment)
  314. END;
  315. ELSIF (recentCommentItem IS SyntaxTree.IfPart) THEN
  316. IF recentCommentItem(SyntaxTree.IfPart).comment = NIL THEN
  317. recentCommentItem(SyntaxTree.IfPart).SetComment(comment)
  318. END;
  319. ELSIF (recentCommentItem IS SyntaxTree.CasePart) THEN
  320. IF recentCommentItem(SyntaxTree.CasePart).comment = NIL THEN
  321. recentCommentItem(SyntaxTree.CasePart).SetComment(comment)
  322. END;
  323. ELSIF (recentCommentItem IS SyntaxTree.WithPart) THEN
  324. IF recentCommentItem(SyntaxTree.WithPart).comment = NIL THEN
  325. recentCommentItem(SyntaxTree.WithPart).SetComment(comment)
  326. END;
  327. END;
  328. comment.SetItem(recentCommentItem,TRUE);
  329. recentComment := NIL;
  330. recentCommentItem := NIL
  331. END;
  332. END;
  333. END;
  334. NextToken;
  335. (*error := ~GetNextToken(token);*)
  336. END;
  337. END SkipComments;
  338. (** Get next token from scanner and store it in object-local variable 'token' *)
  339. PROCEDURE NextToken*;
  340. BEGIN
  341. (*
  342. error := ~GetNextToken(token) OR error;
  343. hasToken := TRUE;
  344. SkipComments();
  345. *)
  346. hasToken := FALSE;
  347. END NextToken;
  348. PROCEDURE Symbol*(): LONGINT;
  349. BEGIN
  350. IF ~hasToken OR (token.symbol = Scanner.Escape) THEN
  351. prevPosition := token.position;
  352. error := ~GetNextToken(token) OR error;
  353. IF token.symbol = Scanner.Escape THEN
  354. error := ~GetNextToken(token) OR error;
  355. END;
  356. hasToken := TRUE;
  357. SkipComments(FALSE);
  358. END;
  359. RETURN token.symbol;
  360. END Symbol;
  361. (* stop on escape symbol *)
  362. PROCEDURE TokenB*(): LONGINT;
  363. BEGIN
  364. IF ~hasToken THEN
  365. prevPosition := token.position;
  366. error := ~GetNextToken(token) OR error;
  367. hasToken := TRUE;
  368. SkipComments(TRUE);
  369. END;
  370. RETURN token.symbol;
  371. END TokenB;
  372. (** Check if current token equals sym. If yes then return true, return false otherwise *)
  373. PROCEDURE PeekB*(symbol: Scanner.Symbol): BOOLEAN;
  374. BEGIN
  375. RETURN TokenB() = symbol
  376. END PeekB;
  377. (** Check if current token equals sym. If yes then return true, return false otherwise *)
  378. PROCEDURE Peek*(symbol: Scanner.Symbol): BOOLEAN;
  379. BEGIN
  380. SkipComments(FALSE);
  381. RETURN Symbol() = symbol
  382. END Peek;
  383. (** Check if the current token equals sym.If yes then read next token, report error otherwise. returns success value *)
  384. PROCEDURE Mandatory*( symbol: Scanner.Symbol): BOOLEAN;
  385. BEGIN
  386. ASSERT( symbol # Scanner.Identifier ); ASSERT( symbol # Scanner.String ); ASSERT( symbol # Scanner.Number ); (* because of NextToken ! *)
  387. IF ~Peek(symbol) THEN
  388. Error( token.position, symbol, "" );
  389. RETURN FALSE
  390. ELSE
  391. NextToken;
  392. RETURN TRUE
  393. END
  394. END Mandatory;
  395. (** Check if the current token equals sym. If yes then read next token, report error otherwise *)
  396. PROCEDURE Check( symbol: Scanner.Symbol );
  397. VAR b: BOOLEAN;
  398. BEGIN
  399. b := Mandatory( symbol );
  400. END Check;
  401. (** Check if current token is an identifier. If yes then copy identifier to name and get next token,
  402. report error otherwise and set name to empty name. returns success value *)
  403. PROCEDURE MandatoryIdentifier( VAR name: SyntaxTree.Identifier): BOOLEAN;
  404. BEGIN
  405. IF Peek(Scanner.Identifier) THEN
  406. name := token.identifier;
  407. NextToken;
  408. RETURN TRUE
  409. ELSE
  410. Error( token.position, Scanner.Identifier, "" );
  411. name := SyntaxTree.invalidIdentifier;
  412. RETURN FALSE
  413. END
  414. END MandatoryIdentifier;
  415. (** Expect an identifier (using MandatoryIdentifier) and return identifier object **)
  416. PROCEDURE Identifier(VAR position: Position): SyntaxTree.Identifier;
  417. VAR name: SyntaxTree.Identifier; identifier: SyntaxTree.Identifier;
  418. BEGIN
  419. position := token.position;
  420. IF MandatoryIdentifier(name) THEN
  421. position := token.position;
  422. identifier := name;
  423. ELSE
  424. identifier := SyntaxTree.invalidIdentifier;
  425. END;
  426. RETURN identifier
  427. END Identifier;
  428. (** Check if current token is a string (or string-like character). If yes then copy identifier to name and get next token,
  429. report error otherwise and set name to empty name. returns success value*)
  430. PROCEDURE MandatoryString*( VAR name: Scanner.StringType ): BOOLEAN;
  431. BEGIN
  432. IF Peek( Scanner.String) THEN
  433. name := token.string;
  434. NextToken;
  435. RETURN TRUE
  436. ELSIF Peek( Scanner.Character) THEN (* for compatibility with release: characters treated as strings *)
  437. name := token.string;
  438. NextToken;
  439. RETURN TRUE
  440. ELSE
  441. Error( token.position, Scanner.String, "" );
  442. NEW(name,1); name^ := "";
  443. RETURN FALSE
  444. END
  445. END MandatoryString;
  446. (** Check if current token is an identifier and if the name matches. If yes then get next token, report error otherwise. returns success value*)
  447. PROCEDURE ExpectThisIdentifier( name: SyntaxTree.Identifier ): BOOLEAN;
  448. VAR string: ARRAY 64 OF CHAR;
  449. BEGIN
  450. IF name = SyntaxTree.invalidIdentifier THEN (* nothing to be expected *)
  451. RETURN TRUE
  452. ELSIF (Symbol() # Scanner.Identifier) OR (token.identifier # name) THEN
  453. Basic.GetString(name,string);
  454. Error( token.position, Scanner.Identifier, string );
  455. RETURN FALSE
  456. ELSE
  457. NextToken;
  458. RETURN TRUE
  459. END
  460. END ExpectThisIdentifier;
  461. (** Check if current token is an identifier and if the name matches. If yes then get next token, report error otherwise. returns success value*)
  462. PROCEDURE ExpectThisString( CONST name: ARRAY OF CHAR ): BOOLEAN;
  463. BEGIN
  464. IF Peek(Scanner.String) & (token.string^ = name) THEN
  465. NextToken;
  466. RETURN TRUE
  467. ELSE
  468. Error( token.position, Scanner.String, name );
  469. RETURN FALSE
  470. END
  471. END ExpectThisString;
  472. (** Check if current token equals sym. If yes then get next token, return false otherwise *)
  473. PROCEDURE Optional*( symbol: Scanner.Symbol ): BOOLEAN;
  474. BEGIN
  475. (* do not use for Identifier, String or Number, if the result is needed ! *)
  476. IF Peek(symbol) THEN
  477. NextToken;
  478. RETURN TRUE
  479. ELSE
  480. RETURN FALSE
  481. END
  482. END Optional;
  483. PROCEDURE OptionalB*( symbol: Scanner.Symbol ): BOOLEAN;
  484. BEGIN
  485. (* do not use for Identifier, String or Number, if the result is needed ! *)
  486. IF PeekB(symbol) THEN
  487. NextToken;
  488. RETURN TRUE
  489. ELSE
  490. RETURN FALSE
  491. END
  492. END OptionalB;
  493. (* ignore one ore more tokens of type symbol *)
  494. PROCEDURE Ignore(symbol: Scanner.Symbol);
  495. BEGIN WHILE Optional(symbol) DO END;
  496. END Ignore;
  497. (** Parsing according to the EBNF **)
  498. (** QualifiedIdentifier = Identifier ['.' Identifier]. **)
  499. PROCEDURE QualifiedIdentifier*( ): SyntaxTree.QualifiedIdentifier;
  500. VAR prefix,suffix: SyntaxTree.Identifier; qualifiedIdentifier: SyntaxTree.QualifiedIdentifier; position0,position1: Position;
  501. BEGIN
  502. IF Trace THEN S( "QualifiedIdentifier" ) END;
  503. prefix := Identifier(position0);
  504. IF prefix # SyntaxTree.invalidIdentifier THEN
  505. IF ~Optional( Scanner.Period )THEN
  506. suffix := prefix; prefix := SyntaxTree.invalidIdentifier; (* empty *)
  507. ELSE
  508. suffix := Identifier(position1);
  509. END;
  510. qualifiedIdentifier := SyntaxTree.NewQualifiedIdentifier( position0, prefix,suffix);
  511. ELSE
  512. qualifiedIdentifier := SyntaxTree.invalidQualifiedIdentifier;
  513. END;
  514. IF Trace THEN E( "QualifiedIdentifier" ) END;
  515. RETURN qualifiedIdentifier
  516. END QualifiedIdentifier;
  517. (** IdentifierDefinition = Identifier [ '*' | '-' ]. **)
  518. PROCEDURE IdentifierDefinition( VAR name: SyntaxTree.Identifier; VAR access: SET; allowedReadOnly: BOOLEAN);
  519. VAR position: Position;
  520. BEGIN
  521. IF Trace THEN S( "IdentifierDefinition" ) END;
  522. name := Identifier(position);
  523. IF Optional( Scanner.Times ) THEN
  524. access := SyntaxTree.Public + SyntaxTree.Protected + SyntaxTree.Internal;
  525. ELSIF Optional( Scanner.Minus ) THEN
  526. IF ~allowedReadOnly THEN
  527. Error( token.position, Basic.InvalidCode, "may not be defined read-only" )
  528. ELSE
  529. access := SyntaxTree.ReadOnly + {SyntaxTree.InternalWrite};
  530. END;
  531. ELSE
  532. access := SyntaxTree.Internal;
  533. END;
  534. IF Trace THEN E( "IdentifierDefinition") END;
  535. END IdentifierDefinition;
  536. (** ExpressionList = Expression { ',' Expression }. **)
  537. PROCEDURE ExpressionList( expressionList: SyntaxTree.ExpressionList );
  538. VAR expression: SyntaxTree.Expression;
  539. BEGIN
  540. IF Trace THEN S( "ExpressionList" ) END;
  541. REPEAT
  542. expression := Expression();
  543. expressionList.AddExpression( expression )
  544. UNTIL ~Optional( Scanner.Comma );
  545. IF Trace THEN E( "ExpressionList" ) END;
  546. END ExpressionList;
  547. (** IndexList = '?' [',' ExpressionList] | Expression { ',' Expression } [',' '?' [',' ExpressionList] ] **)
  548. PROCEDURE IndexList(expressionList: SyntaxTree.ExpressionList);
  549. VAR
  550. position: Position;
  551. done: BOOLEAN;
  552. BEGIN
  553. IF Trace THEN S( "IndexList" ) END;
  554. position := token.position;
  555. IF Optional(Scanner.Questionmark) THEN
  556. expressionList.AddExpression(SyntaxTree.NewTensorRangeExpression(position));
  557. IF Optional(Scanner.Comma) THEN
  558. ExpressionList(expressionList);
  559. END
  560. ELSE
  561. expressionList.AddExpression(Expression());
  562. done := FALSE;
  563. WHILE ~done DO
  564. IF Optional(Scanner.Comma) THEN
  565. IF Optional(Scanner.Questionmark) THEN
  566. expressionList.AddExpression(SyntaxTree.NewTensorRangeExpression(position));
  567. IF Optional(Scanner.Comma) THEN
  568. ExpressionList(expressionList);
  569. END;
  570. done := TRUE;
  571. ELSE
  572. expressionList.AddExpression(Expression())
  573. END
  574. ELSE
  575. done := TRUE
  576. END
  577. END
  578. END;
  579. IF Trace THEN E( "IndexList" ) END;
  580. END IndexList;
  581. (** RangeExpression = SimpleExpression | [SimpleExpression] '..' [SimpleExpression] ['by' SimpleExpression] | '*'.
  582. i.e., a RangeExpression can have one of the following forms:
  583. '*'
  584. '..' [delimiter]
  585. '..' 'by' SimpleExpression
  586. '..' SimpleExpression
  587. '..' SimpleExpression 'by' SimpleExpression
  588. SimpleExpression
  589. SimpleExpression '..' [delimiter]
  590. SimpleExpression '..' 'by' SimpleExpression
  591. SimpleExpression '..' SimpleExpression
  592. SimpleExpression '..' SimpleExpression 'by' SimpleExpression
  593. a RangeExpression is always delimited by any of the following symbols: ",", ";", ":", "]", ")", "}", "=", "#", "END".
  594. **)
  595. PROCEDURE RangeExpression(): SyntaxTree.Expression;
  596. VAR
  597. expression, first, last, step: SyntaxTree.Expression;
  598. position: Position;
  599. PROCEDURE HasDelimiter(): BOOLEAN;
  600. BEGIN RETURN
  601. Peek(Scanner.Comma) OR Peek(Scanner.Semicolon) OR Peek(Scanner.Colon) OR
  602. Peek(Scanner.RightBracket) OR Peek(Scanner.RightParenthesis) OR Peek(Scanner.RightBrace) OR
  603. Peek(Scanner.Equal) OR Peek(Scanner.Unequal) OR Peek(Scanner.End)
  604. END HasDelimiter;
  605. BEGIN
  606. IF Trace THEN S( "RangeExpression" ) END;
  607. position := token.position;
  608. IF Optional(Scanner.Times) THEN
  609. expression := SyntaxTree.NewRangeExpression(position, NIL, NIL, NIL)
  610. ELSIF Optional(Scanner.Upto) THEN
  611. (* is range expression *)
  612. first := NIL;
  613. IF HasDelimiter() THEN
  614. last := NIL;
  615. step := NIL
  616. ELSIF Optional(Scanner.By) THEN
  617. last := NIL;
  618. step := SimpleExpression()
  619. ELSE
  620. last := SimpleExpression();
  621. IF Optional(Scanner.By) THEN
  622. step := SimpleExpression()
  623. ELSE
  624. step := NIL
  625. END
  626. END;
  627. expression := SyntaxTree.NewRangeExpression(position, first, last, step)
  628. ELSE
  629. expression := SimpleExpression();
  630. IF OptionalB(Scanner.Upto) THEN
  631. (* is range expression *)
  632. first := expression;
  633. IF HasDelimiter() THEN
  634. last := NIL;
  635. step := NIL
  636. ELSIF Optional(Scanner.By) THEN
  637. last := NIL;
  638. step := SimpleExpression()
  639. ELSE
  640. last := SimpleExpression();
  641. IF Optional(Scanner.By) THEN
  642. step := SimpleExpression()
  643. ELSE
  644. step := NIL
  645. END
  646. END;
  647. expression := SyntaxTree.NewRangeExpression(position, first, last, step)
  648. END;
  649. END;
  650. IF Trace THEN E( "RangeExpression" ) END;
  651. RETURN expression
  652. END RangeExpression;
  653. (** Designator = ('self' | 'result' | Identifier)
  654. {'.' Identifier | '[' IndexList ']' | '(' [ExpressionList] ')' | '^'} [Flags].
  655. **)
  656. PROCEDURE Designator( ): SyntaxTree.Designator;
  657. VAR
  658. designator: SyntaxTree.Designator; expressionList: SyntaxTree.ExpressionList;
  659. identifier: SyntaxTree.Identifier; position: Position;
  660. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
  661. qualifiedType : SyntaxTree.QualifiedType;
  662. BEGIN
  663. IF Trace THEN S( "Designator" ) END;
  664. position := token.position;
  665. IF Optional(Scanner.Self) THEN
  666. designator := SyntaxTree.NewSelfDesignator(position);
  667. ELSIF Optional(Scanner.Result) THEN
  668. designator := SyntaxTree.NewResultDesignator(position);
  669. (* ADDRESS AND SIZE can be type identifiers used for type conversion *)
  670. ELSIF (Symbol() = Scanner.Address) OR (Symbol()=Scanner.Size) THEN
  671. identifier := token.identifier;
  672. designator := SyntaxTree.NewIdentifierDesignator(position,identifier);
  673. NextToken;
  674. ELSIF (Symbol() = Scanner.New) THEN
  675. identifier := token.identifier;
  676. designator := SyntaxTree.NewIdentifierDesignator(position,identifier);
  677. NextToken;
  678. IF Symbol() # Scanner.LeftParenthesis THEN (* NEW Type () *)
  679. qualifiedIdentifier := QualifiedIdentifier();
  680. qualifiedType := SyntaxTree.NewQualifiedType(qualifiedIdentifier.position, currentScope, qualifiedIdentifier);
  681. IF Mandatory( Scanner.LeftParenthesis ) THEN
  682. expressionList := SyntaxTree.NewExpressionList();
  683. IF ~Optional(Scanner.RightParenthesis) THEN
  684. ExpressionList( expressionList );
  685. Check( Scanner.RightParenthesis )
  686. END;
  687. END;
  688. designator := SyntaxTree.NewBuiltinCallDesignator(position,Global.New, NIL, expressionList);
  689. designator(SyntaxTree.BuiltinCallDesignator).SetReturnType(qualifiedType);
  690. (* special case: NEW Type() *)
  691. END;
  692. ELSE
  693. identifier := Identifier(position);
  694. designator := SyntaxTree.NewIdentifierDesignator(position,identifier);
  695. END;
  696. designator.End(token.position);
  697. LOOP
  698. position := token.position;
  699. IF OptionalB( Scanner.LeftParenthesis ) THEN
  700. expressionList := SyntaxTree.NewExpressionList();
  701. IF ~Optional( Scanner.RightParenthesis ) THEN
  702. ExpressionList( expressionList );
  703. Check( Scanner.RightParenthesis )
  704. END;
  705. designator := SyntaxTree.NewParameterDesignator( position,designator,expressionList);
  706. ELSIF OptionalB( Scanner.Period ) THEN
  707. IF ~Optional(Scanner.Identifier) THEN (* make sure token is read *) END;
  708. position := token.position;
  709. CASE token.identifierString[0] OF
  710. "a".."z", "A" .. "Z":
  711. (*IF Peek(Scanner.Size) (* special rule: support for SYSTEM.SIZE *) THEN*)
  712. identifier := token.identifier;
  713. NextToken;
  714. ELSE
  715. identifier := Identifier(position);
  716. END;
  717. designator := SyntaxTree.NewSelectorDesignator(position,designator,identifier);
  718. ELSIF OptionalB( Scanner.LeftBracket ) THEN
  719. expressionList := SyntaxTree.NewExpressionList();
  720. IndexList( expressionList );
  721. Check( Scanner.RightBracket );
  722. designator:= SyntaxTree.NewBracketDesignator( position,designator,expressionList );
  723. ELSIF OptionalB( Scanner.Arrow ) THEN
  724. designator:= SyntaxTree.NewArrowDesignator( position,designator );
  725. ELSE EXIT
  726. END;
  727. designator.End(token.position);
  728. END;
  729. IF OptionalB(Scanner.LeftBrace) THEN
  730. designator.SetModifiers(Flags());
  731. END;
  732. designator.End(token.position);
  733. (*IF OptionalB(Scanner.Escape) THEN END; (* skip breaking signal *)*)
  734. IF Trace THEN E( "Designator" ) END;
  735. RETURN designator
  736. END Designator;
  737. (** Set = '{' [ RangeExpression {',' RangeExpression} ] '}'. **)
  738. PROCEDURE Set( ): SyntaxTree.Expression;
  739. VAR
  740. set: SyntaxTree.Set;
  741. BEGIN
  742. IF Trace THEN S( "Set" ) END;
  743. set := SyntaxTree.NewSet(token.position);
  744. Check(Scanner.LeftBrace);
  745. IF ~Optional(Scanner.RightBrace) THEN
  746. REPEAT
  747. set.elements.AddExpression(RangeExpression())
  748. UNTIL ~Optional(Scanner.Comma);
  749. Check(Scanner.RightBrace);
  750. END;
  751. set.End(token.position);
  752. IF Trace THEN E( "Set" ) END;
  753. RETURN set
  754. END Set;
  755. (* MathArray = '[' Expression {',' Expression} ']'. *)
  756. PROCEDURE MathArray(): SyntaxTree.Expression;
  757. VAR array: SyntaxTree.MathArrayExpression; element: SyntaxTree.Expression;
  758. BEGIN
  759. array := SyntaxTree.NewMathArrayExpression(token.position);
  760. IF ~Optional(Scanner.RightBracket) THEN
  761. REPEAT
  762. element := Expression();
  763. array.elements.AddExpression(element);
  764. UNTIL ~Optional(Scanner.Comma);
  765. Check(Scanner.RightBracket);
  766. END;
  767. array.End(token.position);
  768. RETURN array
  769. END MathArray;
  770. (** Factor = Number | Character | String | 'nil' | 'imag' | 'true' | 'false' | Set
  771. | '(' Expression ')' | '~' Factor | Factor '`' | Designator | MathArray.
  772. | 'SIZE' 'OF' Designator | 'ADDRESS' 'OF' Designator | 'ALIAS' OF Expression
  773. **)
  774. PROCEDURE Factor( ): SyntaxTree.Expression;
  775. VAR factor: SyntaxTree.Expression; position: Position; operator: LONGINT;
  776. BEGIN
  777. IF Trace THEN S( "Factor" ) END;
  778. position := token.position;
  779. CASE Symbol() OF
  780. | Scanner.Number:
  781. IF (token.numberType = Scanner.Integer) THEN
  782. factor := SyntaxTree.NewIntegerValue( position, token.integer);
  783. ELSIF (token.numberType = Scanner.Hugeint) THEN
  784. factor := SyntaxTree.NewIntegerValue(position, token.hugeint);
  785. ELSIF (token.numberType = Scanner.Real) OR (token.numberType = Scanner.Longreal) THEN
  786. factor := SyntaxTree.NewRealValue( position, token.real);
  787. factor(SyntaxTree.RealValue).SetSubtype(token.numberType);
  788. ELSE HALT( 100 )
  789. END;
  790. NextToken;
  791. | Scanner.Character:
  792. factor := SyntaxTree.NewCharacterValue(position,token.character);
  793. NextToken;
  794. | Scanner.String:
  795. factor := SyntaxTree.NewStringValue( position, token.string );
  796. NextToken;
  797. WHILE (Symbol() = Scanner.String) OR (Symbol() = Scanner.Character) DO
  798. IF Symbol() = Scanner.Character THEN
  799. factor(SyntaxTree.StringValue).AppendChar(token.character);
  800. ELSE
  801. factor(SyntaxTree.StringValue).Append(token.string);
  802. END;
  803. factor.End(token.position);
  804. NextToken;
  805. END;
  806. | Scanner.Nil:
  807. factor := SyntaxTree.NewNilValue( position );
  808. NextToken;
  809. | Scanner.Imag:
  810. factor := SyntaxTree.NewComplexValue(position, 0, 1);
  811. factor(SyntaxTree.ComplexValue).SetSubtype(Scanner.Real);
  812. NextToken;
  813. | Scanner.True:
  814. factor := SyntaxTree.NewBooleanValue( position, TRUE );
  815. NextToken;
  816. | Scanner.False:
  817. factor := SyntaxTree.NewBooleanValue( position, FALSE );
  818. NextToken;
  819. | Scanner.LeftBrace:
  820. factor := Set();
  821. | Scanner.LeftParenthesis:
  822. NextToken;
  823. factor := Expression();
  824. Check( Scanner.RightParenthesis );
  825. factor.End( token.position);
  826. | Scanner.Not:
  827. NextToken;
  828. factor := Factor();
  829. factor := SyntaxTree.NewUnaryExpression( position, factor, Scanner.Not );
  830. factor.End( token.position);
  831. | Scanner.Address, Scanner.Size:
  832. operator := Symbol();
  833. factor := Designator(); (* ADDRESS AND SIZE can be type identifiers used for type conversion *)
  834. IF Optional(Scanner.Of) THEN
  835. factor := Designator();
  836. factor := SyntaxTree.NewUnaryExpression( position, factor, operator );
  837. END;
  838. factor.End (token.position)
  839. | Scanner.Alias:
  840. operator := Symbol();
  841. NextToken();
  842. IF Mandatory(Scanner.Of) THEN
  843. factor := Factor();
  844. factor := SyntaxTree.NewUnaryExpression( position, factor, operator );
  845. END;
  846. factor.End (token.position)
  847. | Scanner.Self, Scanner.Result, Scanner.Identifier, Scanner.New:
  848. factor := Designator();
  849. factor.End( token.position);
  850. | Scanner.LeftBracket:
  851. NextToken;
  852. factor := MathArray();
  853. factor.End(token.position);
  854. ELSE
  855. Error( position, Basic.ValueStartIncorrectSymbol, "" );
  856. NextToken; factor := SyntaxTree.invalidExpression;
  857. END;
  858. (* suffix *)
  859. IF OptionalB(Scanner.Transpose) THEN
  860. IF (factor IS SyntaxTree.UnaryExpression) & (factor(SyntaxTree.UnaryExpression).operator = Scanner.Transpose) THEN
  861. (* transpose operator has higher precedence than not, reevaluate expression: *)
  862. factor := factor(SyntaxTree.UnaryExpression).left;
  863. factor := SyntaxTree.NewUnaryExpression(position,factor,Scanner.Transpose);
  864. factor := SyntaxTree.NewUnaryExpression(position,factor,Scanner.Not);
  865. ELSE
  866. factor := SyntaxTree.NewUnaryExpression(position,factor,Scanner.Transpose);
  867. END;
  868. END;
  869. IF Trace THEN E( "Factor" ) END;
  870. RETURN factor
  871. END Factor;
  872. (** Term = Factor {MulOp Factor}.
  873. MulOp = '*' | '**' | '.*' | '+*' | '/' | '\' | './' | 'div' | 'mod' | '&'.
  874. **)
  875. PROCEDURE Term( ): SyntaxTree.Expression;
  876. VAR term, factor: SyntaxTree.Expression; operator: LONGINT; position: Position;
  877. BEGIN
  878. IF Trace THEN S( "Term" ) END;
  879. position := token.position;
  880. term := Factor();
  881. WHILE (TokenB() >= Scanner.Times) & (TokenB() <= Scanner.And) DO
  882. operator := Symbol();
  883. NextToken;
  884. factor := Factor();
  885. term := SyntaxTree.NewBinaryExpression( position, term, factor, operator );
  886. END;
  887. term.End( token.position);
  888. IF Trace THEN E( "Term" ) END;
  889. RETURN term
  890. END Term;
  891. (** SimpleExpression = ['+'|'-'] Term {AddOp Term}.
  892. AddOp = '+' | '-' | 'or'.
  893. **)
  894. PROCEDURE SimpleExpression( ): SyntaxTree.Expression;
  895. VAR operator: LONGINT; term, expression: SyntaxTree.Expression; position: Position;
  896. BEGIN
  897. IF Trace THEN S( "SimpleExpression" ) END;
  898. position := token.position;
  899. IF Peek(Scanner.Plus) OR Peek(Scanner.Minus) THEN (* sign should be part of the factor *)
  900. operator := Symbol();
  901. NextToken;
  902. term := Term();
  903. expression := SyntaxTree.NewUnaryExpression( position, term, operator );
  904. ELSE expression := Term();
  905. END;
  906. WHILE (TokenB() >= Scanner.Or) & (TokenB() <= Scanner.Minus) DO
  907. operator := Symbol();
  908. NextToken;
  909. term := Term();
  910. expression := SyntaxTree.NewBinaryExpression( position, expression, term, operator );
  911. END;
  912. IF Trace THEN E( "SimpleExpression" ) END;
  913. RETURN expression
  914. END SimpleExpression;
  915. (**
  916. Expression = RangeExpression [RelationOp RangeExpression].
  917. RelationOp = '=' | '.=' | '#' | '.#'
  918. | '<' | '.<' | '<=' | '.<=' | '>' | '.>' | '>=' | '.>='
  919. | '??' | '!!' | '<<?' | '>>?'
  920. | 'in' | 'is'
  921. **)
  922. PROCEDURE Expression*( ): SyntaxTree.Expression;
  923. VAR expression, rightExpression: SyntaxTree.Expression; operator: LONGINT; position: Position;
  924. BEGIN
  925. IF Trace THEN S( "Expression" ) END;
  926. expression := RangeExpression();
  927. position := expression.position;
  928. IF (TokenB() >= Scanner.Equal) & (TokenB() <= Scanner.Is) THEN
  929. operator := Symbol();
  930. NextToken;
  931. rightExpression := RangeExpression();
  932. expression := SyntaxTree.NewBinaryExpression(position, expression, rightExpression, operator );
  933. expression.End(token.position);
  934. END;
  935. (*IF OptionalB(Scanner.Escape) THEN END; (* skip breaking escape *)*)
  936. IF Trace THEN E( "Expression" ) END;
  937. RETURN expression
  938. END Expression;
  939. (** Case = RangeExpression {',' RangeExpression} ':' StatementSequence. **)
  940. PROCEDURE Case( caseStatement: SyntaxTree.CaseStatement );
  941. VAR
  942. casePart: SyntaxTree.CasePart;
  943. statements: SyntaxTree.StatementSequence;
  944. element: SyntaxTree.Expression;
  945. BEGIN
  946. IF Trace THEN S( "Case" ) END;
  947. casePart := SyntaxTree.NewCasePart();
  948. casePart.SetPosition(token.position);
  949. CommentCasePart(casePart);
  950. REPEAT
  951. element := RangeExpression();
  952. casePart.elements.AddExpression( element );
  953. UNTIL ~Optional( Scanner.Comma );
  954. Check( Scanner.Colon );
  955. statements := StatementSequence(caseStatement);
  956. casePart.SetStatements( statements );
  957. caseStatement.AddCasePart( casePart );
  958. casePart.SetEnd(token.position);
  959. IF Trace THEN E( "Case" ) END;
  960. END Case;
  961. (** Statement =
  962. [
  963. Designator [':=' Expression |'!' Expression | '?' Expression | '<<' Expresssion | '>>' Expression]
  964. | 'if' Expression 'then' StatementSequence
  965. {'elsif' Expression 'then' StatementSequence}
  966. ['else' StatementSequence]
  967. 'end'
  968. | 'with' Identifier ':' QualifiedIdentifier 'do' StatementSequence
  969. {'|' [Identifier ':'] QualifiedIdentifier 'do' StatementSequence}
  970. [else StatementSequence]
  971. 'end'
  972. | 'case' Expression 'of' ['|'] Case {'|' Case} ['else' StatementSequence] 'end'
  973. | 'while' Expression 'do' StatementSequence 'end'
  974. | 'repeat' StatementSequence 'until' Expression
  975. | 'for' Identifier ':=' Expression 'to' Expression ['by' Expression] 'do'
  976. StatementSequence 'end'
  977. | 'loop' StatementSequence 'end'
  978. | 'exit'
  979. | 'return' [Expression]
  980. | 'await' Expression
  981. | 'begin' StatementBlock 'end'
  982. | 'code' {any} 'end'
  983. ].
  984. **)
  985. PROCEDURE Statement*( statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement): BOOLEAN;
  986. VAR qualifiedIdentifier: SyntaxTree.QualifiedIdentifier; expression: SyntaxTree.Expression; designator: SyntaxTree.Designator; statement: SyntaxTree.Statement;
  987. ifStatement: SyntaxTree.IfStatement; elsifPart: SyntaxTree.IfPart; statementSequence: SyntaxTree.StatementSequence; withStatement: SyntaxTree.WithStatement;
  988. withPart: SyntaxTree.WithPart; caller: SyntaxTree.ProcedureCallStatement;
  989. caseStatement: SyntaxTree.CaseStatement; whileStatement: SyntaxTree.WhileStatement; repeatStatement: SyntaxTree.RepeatStatement; forStatement: SyntaxTree.ForStatement;
  990. identifier: SyntaxTree.Identifier; loopStatement: SyntaxTree.LoopStatement; returnStatement: SyntaxTree.ReturnStatement; awaitStatement: SyntaxTree.AwaitStatement;
  991. qualifiedType: SyntaxTree.QualifiedType; code : SyntaxTree.Code; position: Position; result: BOOLEAN;
  992. commToken: Scanner.Symbol;
  993. BEGIN
  994. IF Trace THEN S( "Statement" ) END;
  995. CASE Symbol() OF
  996. | Scanner.Identifier, Scanner.Self, Scanner.Result, Scanner.New:
  997. designator := Designator();
  998. position := token.position;
  999. IF OptionalB( Scanner.Becomes ) THEN
  1000. expression := Expression();
  1001. statement := SyntaxTree.NewAssignment( position, designator, expression,outer );
  1002. CommentStatement(statement);
  1003. ELSIF PeekB(Scanner.ExclamationMark) OR PeekB(Scanner.Questionmark) OR PeekB(Scanner.LessLess) OR PeekB(Scanner.GreaterGreater) THEN
  1004. commToken := Symbol();
  1005. NextToken;
  1006. expression := Expression();
  1007. statement := SyntaxTree.NewCommunicationStatement(position, commToken, designator, expression, outer);
  1008. CommentStatement(statement);
  1009. ELSE
  1010. caller := SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator,outer);
  1011. statement := caller;
  1012. CommentStatement(statement);
  1013. END;
  1014. statement.End(prevPosition);
  1015. statements.AddStatement( statement );
  1016. (*IF OptionalB(Scanner.Escape) THEN END;*)
  1017. result := TRUE
  1018. | Scanner.If:
  1019. NextToken;
  1020. ifStatement := SyntaxTree.NewIfStatement( token.position ,outer);
  1021. CommentStatement(ifStatement);
  1022. expression := Expression();
  1023. ifStatement.ifPart.SetCondition( expression );
  1024. Check( Scanner.Then );
  1025. statementSequence := StatementSequence(ifStatement);
  1026. ifStatement.ifPart.SetStatements( statementSequence );
  1027. ifStatement.ifPart.SetEnd(token.position);
  1028. WHILE Optional( Scanner.Elsif ) DO
  1029. elsifPart := SyntaxTree.NewIfPart();
  1030. elsifPart.SetPosition(token.position);
  1031. CommentIfPart(elsifPart);
  1032. ifStatement.AddElsifPart( elsifPart);
  1033. expression := Expression();
  1034. elsifPart.SetCondition( expression );
  1035. Check( Scanner.Then );
  1036. statementSequence := StatementSequence(ifStatement);
  1037. elsifPart.SetStatements( statementSequence );
  1038. elsifPart.SetEnd(token.position);
  1039. END;
  1040. IF Optional( Scanner.Else ) THEN
  1041. statementSequence := StatementSequence(ifStatement);
  1042. ifStatement.SetElsePart( statementSequence );
  1043. END;
  1044. ifStatement.End(token.position);
  1045. Check( Scanner.End ); statements.AddStatement( ifStatement );
  1046. result := TRUE
  1047. | Scanner.With:
  1048. withStatement := SyntaxTree.NewWithStatement( token.position ,outer);
  1049. CommentStatement(withStatement);
  1050. NextToken;
  1051. identifier := Identifier(position);
  1052. IF Optional(Scanner.Period) & Optional(Scanner.Identifier) THEN
  1053. Error(position,Basic.InvalidCode,"forbidden qualified identifier in with statement");
  1054. END;
  1055. designator := SyntaxTree.NewIdentifierDesignator(position,identifier);
  1056. withStatement.SetVariable(designator);
  1057. Check( Scanner.Colon );
  1058. IF Optional(Scanner.Bar) THEN (* ignore *) END;
  1059. REPEAT
  1060. withPart := SyntaxTree.NewWithPart();
  1061. withPart.SetPosition(token.position);
  1062. CommentWithPart(withPart);
  1063. withStatement.AddWithPart(withPart);
  1064. qualifiedIdentifier := QualifiedIdentifier();
  1065. IF Optional(Scanner.Colon) THEN (* compatibility with old format *)
  1066. Basic.Warning(diagnostics, scanner.source^, qualifiedIdentifier.position, "deprecated form of with statement, remove the repeated variable");
  1067. qualifiedIdentifier := QualifiedIdentifier();
  1068. END;
  1069. qualifiedType := SyntaxTree.NewQualifiedType(qualifiedIdentifier.position, currentScope, qualifiedIdentifier);
  1070. withPart.SetType(qualifiedType);
  1071. Check( Scanner.Do );
  1072. statementSequence := StatementSequence(withStatement);
  1073. withPart.SetStatements( statementSequence );
  1074. withPart.SetEnd(token.position);
  1075. UNTIL ~Optional(Scanner.Bar) OR ~CascadedWithSupport;
  1076. IF CascadedWithSupport & Optional(Scanner.Else) THEN
  1077. statementSequence := StatementSequence(withStatement);
  1078. withStatement.SetElsePart(statementSequence);
  1079. END;
  1080. Check( Scanner.End );
  1081. withStatement.End(token.position);
  1082. statements.AddStatement( withStatement );
  1083. result := TRUE
  1084. | Scanner.Case:
  1085. caseStatement := SyntaxTree.NewCaseStatement( token.position,outer );
  1086. CommentStatement(caseStatement);
  1087. NextToken;
  1088. expression := Expression();
  1089. Check( Scanner.Of );
  1090. caseStatement.SetVariable( expression );
  1091. IF Optional(Scanner.Bar) THEN END;
  1092. REPEAT
  1093. Case(caseStatement)
  1094. UNTIL ~Optional(Scanner.Bar);
  1095. IF Optional( Scanner.Else ) THEN
  1096. statementSequence := StatementSequence(caseStatement);
  1097. caseStatement.SetElsePart( statementSequence );
  1098. END;
  1099. Check( Scanner.End );
  1100. caseStatement.End(token.position);
  1101. statements.AddStatement( caseStatement );
  1102. result := TRUE
  1103. | Scanner.While:
  1104. NextToken;
  1105. whileStatement := SyntaxTree.NewWhileStatement( token.position, outer );
  1106. CommentStatement(whileStatement);
  1107. expression := Expression();
  1108. Check( Scanner.Do );
  1109. whileStatement.SetCondition( expression );
  1110. statementSequence := StatementSequence(whileStatement);
  1111. whileStatement.SetStatements( statementSequence );
  1112. Check( Scanner.End );
  1113. whileStatement.End(token.position);
  1114. statements.AddStatement( whileStatement );
  1115. result := TRUE
  1116. | Scanner.Repeat:
  1117. NextToken;
  1118. repeatStatement := SyntaxTree.NewRepeatStatement( token.position, outer );
  1119. CommentStatement(repeatStatement);
  1120. statementSequence := StatementSequence(repeatStatement);
  1121. repeatStatement.SetStatements( statementSequence );
  1122. Check( Scanner.Until );
  1123. expression := Expression();
  1124. repeatStatement.End(prevPosition);
  1125. repeatStatement.SetCondition( expression );
  1126. statements.AddStatement( repeatStatement );
  1127. result := TRUE
  1128. | Scanner.For:
  1129. NextToken;
  1130. forStatement := SyntaxTree.NewForStatement( token.position, outer);
  1131. CommentStatement(forStatement);
  1132. identifier := Identifier(position);
  1133. IF Optional(Scanner.Period) & Optional(Scanner.Identifier) THEN
  1134. Error(position,Basic.InvalidCode,"forbidden non-local counter variable");
  1135. END;
  1136. designator := SyntaxTree.NewIdentifierDesignator(position,identifier);
  1137. forStatement.SetVariable( designator );
  1138. Check( Scanner.Becomes );
  1139. expression := Expression();
  1140. forStatement.SetFrom( expression );
  1141. Check( Scanner.To );
  1142. expression := Expression();
  1143. forStatement.SetTo( expression );
  1144. IF Optional( Scanner.By ) THEN
  1145. expression := Expression();
  1146. forStatement.SetBy( expression );
  1147. END;
  1148. Check( Scanner.Do );
  1149. statementSequence := StatementSequence(forStatement);
  1150. forStatement.SetStatements( statementSequence );
  1151. Check( Scanner.End );
  1152. forStatement.End(token.position);
  1153. statements.AddStatement( forStatement );
  1154. result := TRUE
  1155. | Scanner.Loop:
  1156. NextToken;
  1157. loopStatement := SyntaxTree.NewLoopStatement( token.position ,outer);
  1158. CommentStatement(loopStatement);
  1159. statementSequence := StatementSequence(loopStatement);
  1160. loopStatement.SetStatements( statementSequence );
  1161. Check( Scanner.End );
  1162. loopStatement.End(token.position);
  1163. statements.AddStatement( loopStatement );
  1164. result := TRUE;
  1165. | Scanner.Exit:
  1166. NextToken;
  1167. statement := SyntaxTree.NewExitStatement( token.position, outer);
  1168. CommentStatement(statement);
  1169. statements.AddStatement( statement );
  1170. result := TRUE;
  1171. | Scanner.Return:
  1172. NextToken;
  1173. returnStatement := SyntaxTree.NewReturnStatement( token.position, outer);
  1174. CommentStatement(returnStatement);
  1175. IF (Symbol() >= Scanner.Plus) & (Symbol() <= Scanner.Identifier) THEN
  1176. expression := Expression();
  1177. returnStatement.SetReturnValue( expression );
  1178. END;
  1179. returnStatement.End(token.position);
  1180. statements.AddStatement( returnStatement );
  1181. result := TRUE;
  1182. | Scanner.Ignore:
  1183. position := token.position;
  1184. CommentStatement(statement);
  1185. NextToken;
  1186. designator := Designator();
  1187. caller := SyntaxTree.NewProcedureCallStatement(designator.position, TRUE, designator,outer);
  1188. statements.AddStatement( caller );
  1189. result := TRUE;
  1190. | Scanner.Begin:
  1191. NextToken; statement := StatementBlock(outer); statements.AddStatement( statement ); Check( Scanner.End );
  1192. statement.End(token.position);
  1193. result := TRUE;
  1194. | Scanner.Await:
  1195. awaitStatement := SyntaxTree.NewAwaitStatement( token.position, outer );
  1196. CommentStatement(awaitStatement);
  1197. NextToken;
  1198. expression := Expression();
  1199. awaitStatement.SetCondition( expression );
  1200. statements.AddStatement( awaitStatement );
  1201. awaitStatement.End(token.position);
  1202. result := TRUE
  1203. | Scanner.Code:
  1204. (* assemble *)
  1205. code := Code(outer);
  1206. Check(Scanner.End);
  1207. code.End(token.position);
  1208. statements.AddStatement( code );
  1209. result := TRUE
  1210. | Scanner.End: result := FALSE (* end of if, with, case, while, for, loop, or statement sequence *)
  1211. | Scanner.Until: result := FALSE (* end of repeat *)
  1212. | Scanner.Else: result := FALSE (* else of if or case *)
  1213. | Scanner.Elsif: result := FALSE (* elsif of if *)
  1214. | Scanner.Bar: result := FALSE (* next case *)
  1215. | Scanner.Finally: result := FALSE (* end block by finally statement *)
  1216. | Scanner.Semicolon: result := FALSE (* allow the empty statement *)
  1217. (* builtin pseudo procedures are resolved by checker *)
  1218. ELSE
  1219. result := FALSE;
  1220. (*
  1221. IF Lax THEN
  1222. expression := Expression();
  1223. statement := SyntaxTree.NewAssignment( position, NIL, expression,outer );
  1224. statements.AddStatement(statement);
  1225. result := ~error;
  1226. ELSE
  1227. result := FALSE;
  1228. END;
  1229. *)
  1230. END;
  1231. IF Trace THEN E( "Statement" ) END;
  1232. RETURN result
  1233. END Statement;
  1234. (** StatementSequence = Statement {';' Statement}. **)
  1235. PROCEDURE StatementSequence*(outer: SyntaxTree.Statement ): SyntaxTree.StatementSequence;
  1236. VAR statements: SyntaxTree.StatementSequence; b: BOOLEAN;
  1237. BEGIN
  1238. IF Trace THEN S( "StatementSequence" ) END;
  1239. statements := SyntaxTree.NewStatementSequence();
  1240. IF Lax THEN
  1241. WHILE ~Peek(Scanner.Return) & Statement(statements,outer) DO Ignore(Scanner.Semicolon) END;
  1242. IF Peek(Scanner.Return) & Statement(statements,outer) THEN Ignore(Scanner.Semicolon) END; (* return bound to end of statement sequence *)
  1243. ELSE
  1244. REPEAT
  1245. b := Statement( statements,outer )
  1246. UNTIL ~Optional( Scanner.Semicolon );
  1247. END;
  1248. IF Trace THEN E( "StatementSequence" ) END;
  1249. RETURN statements
  1250. END StatementSequence;
  1251. (** StatementBlock = [Flags] StatementSequence. **)
  1252. PROCEDURE StatementBlock(outer: SyntaxTree.Statement): SyntaxTree.StatementBlock;
  1253. VAR block: SyntaxTree.StatementBlock; position: Position;
  1254. BEGIN
  1255. IF Trace THEN S( "StatementBlock" ) END;
  1256. position := token.position;
  1257. position.start := position.end;
  1258. block := SyntaxTree.NewStatementBlock( position, outer, NIL );
  1259. CommentStatement(block);
  1260. IF Optional( Scanner.LeftBrace ) THEN
  1261. block.SetModifier(Flags());
  1262. END;
  1263. block.SetStatementSequence( StatementSequence(block) );
  1264. IF Trace THEN E( "StatementBlock" ) END;
  1265. RETURN block
  1266. END StatementBlock;
  1267. (** Code = { any \ 'end' \ 'with' } ['with' {('in'|'out') StatementSequence}] . **)
  1268. PROCEDURE Code(outer: SyntaxTree.Statement): SyntaxTree.Code;
  1269. VAR startPos: Position; endPos, i ,len: LONGINT; codeString: Scanner.StringType; code: SyntaxTree.Code;
  1270. end: Scanner.Symbol; in, out: BOOLEAN; statements, rules: SyntaxTree.StatementSequence;
  1271. BEGIN
  1272. startPos := token.position;
  1273. end := scanner.SkipToEndOfCode(startPos.start, endPos, token);
  1274. codeString := token.string;
  1275. WHILE (end = Scanner.Unequal) & ConditionalStatement (token) DO
  1276. end := scanner.SkipToEndOfCode(startPos.start, endPos, token);
  1277. IF (conditional = Processing) OR (conditional = ProcessingElse) THEN
  1278. codeString := Strings.ConcatToNew (codeString^, token.string^);
  1279. END;
  1280. END;
  1281. IF (end = Scanner.End) OR (end = Scanner.With) THEN
  1282. code := SyntaxTree.NewCode(startPos,outer);
  1283. i := 0; len := LEN(codeString^);
  1284. code.SetSourceCode(codeString,len);
  1285. IF (end = Scanner.With) & Mandatory(Scanner.With) THEN
  1286. in := Optional(Scanner.In);
  1287. out := Optional(Scanner.Out);
  1288. WHILE in OR out DO
  1289. statements := StatementSequence(code);
  1290. IF in THEN rules := code.inRules ELSE rules := code.outRules END;
  1291. FOR i := 0 TO statements.Length()-1 DO
  1292. rules.AddStatement(statements.GetStatement(i));
  1293. END;
  1294. in := Optional(Scanner.In);
  1295. out := Optional(Scanner.Out);
  1296. END;
  1297. END;
  1298. END;
  1299. RETURN code;
  1300. END Code;
  1301. (** Body = 'begin' [Flags] StatementSequence ['finally' StatementSequence]
  1302. | 'code' Code. **)
  1303. PROCEDURE Body( scope: SyntaxTree.ProcedureScope ): SyntaxTree.Body;
  1304. VAR body: SyntaxTree.Body; code: SyntaxTree.Code; position: Position; previousScope: SyntaxTree.Scope;
  1305. BEGIN
  1306. previousScope := currentScope;
  1307. currentScope := scope;
  1308. IF Trace THEN S( "Body" ) END;
  1309. IF Peek( Scanner.Code ) THEN
  1310. body := SyntaxTree.NewBody(token.position,scope); (* empty body for the time being *)
  1311. (* assemble *)
  1312. code := Code(body);
  1313. body.SetCode(code);
  1314. ELSIF Mandatory( Scanner.Begin ) THEN
  1315. body := SyntaxTree.NewBody(token.position,scope);
  1316. IF Optional( Scanner.LeftBrace ) THEN
  1317. body.SetModifier(Flags());
  1318. END;
  1319. position := token.position;
  1320. body.SetStatementSequence(StatementSequence(body));
  1321. IF Optional( Scanner.Finally ) THEN
  1322. body.SetFinally(StatementSequence(body));
  1323. END;
  1324. END;
  1325. body.End(token.position); (* beginning of "end" is end of body *)
  1326. IF Trace THEN E( "Body" ) END;
  1327. currentScope := previousScope;
  1328. RETURN body
  1329. END Body;
  1330. (** wrapper for a body in records and modules *)
  1331. PROCEDURE BodyProcedure(parentScope: SyntaxTree.Scope): SyntaxTree.Procedure;
  1332. VAR procedureScope: SyntaxTree.ProcedureScope; procedure: SyntaxTree.Procedure;
  1333. BEGIN
  1334. procedureScope := SyntaxTree.NewProcedureScope(parentScope);
  1335. IF parentScope IS SyntaxTree.ModuleScope THEN
  1336. procedure := SyntaxTree.NewProcedure( token.position, Global.ModuleBodyName,procedureScope);
  1337. procedure.SetAccess(SyntaxTree.Hidden);
  1338. ELSE
  1339. procedure := SyntaxTree.NewProcedure( token.position, Global.RecordBodyName,procedureScope);
  1340. (*! todo: make this a hidden token. Problematic when used with paco. *)
  1341. procedure.SetAccess(SyntaxTree.Public + SyntaxTree.Protected + SyntaxTree.Internal);
  1342. END;
  1343. parentScope.AddProcedureDeclaration(procedure);
  1344. procedure.SetType(SyntaxTree.NewProcedureType(SyntaxTree.invalidPosition,parentScope));
  1345. procedure.SetBodyProcedure(TRUE);
  1346. procedureScope.SetBody(Body(procedureScope));
  1347. RETURN procedure
  1348. END BodyProcedure;
  1349. (* ProcedureType = 'procedure' [Flags] [FormalParameters]. *)
  1350. PROCEDURE ProcedureType(position: Position; parentScope: SyntaxTree.Scope): SyntaxTree.ProcedureType;
  1351. VAR procedureType: SyntaxTree.ProcedureType;
  1352. BEGIN
  1353. IF Trace THEN S( "ProcedureType" ) END;
  1354. (* procedure token already consumed *)
  1355. procedureType := SyntaxTree.NewProcedureType( position, parentScope);
  1356. IF Optional(Scanner.LeftBrace) THEN
  1357. procedureType.SetModifiers(Flags());
  1358. END;
  1359. IF Optional(Scanner.LeftParenthesis) THEN FormalParameters( procedureType, parentScope) END;
  1360. IF Trace THEN E( "ProcedureType" )
  1361. END;
  1362. RETURN procedureType;
  1363. END ProcedureType;
  1364. (** ObjectType = 'object' | 'object' [Flags] ['(' QualifiedIdentifier ')'] DeclarationSequence [Body] 'end' [Identifier] . **)
  1365. PROCEDURE ObjectType(position: Position; name: SyntaxTree.Identifier; parentScope: SyntaxTree.Scope ): SyntaxTree.Type;
  1366. VAR
  1367. objectType: SyntaxTree.RecordType;
  1368. pointerType: SyntaxTree.PointerType;
  1369. recordScope: SyntaxTree.RecordScope;
  1370. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
  1371. baseType: SyntaxTree.Type;
  1372. identifier: SyntaxTree.Identifier;
  1373. type: SyntaxTree.Type;
  1374. modifiers: SyntaxTree.Modifier;
  1375. BEGIN
  1376. IF Trace THEN S( "ObjectType" ) END;
  1377. (* token object already consumed *)
  1378. (* generic empty OBJECT type *)
  1379. IF Peek(Scanner.Semicolon) OR Peek(Scanner.RightParenthesis) THEN
  1380. Scanner.GetKeyword(scanner.case,Scanner.Object,identifier);
  1381. qualifiedIdentifier := SyntaxTree.NewQualifiedIdentifier(position,SyntaxTree.invalidIdentifier,identifier);
  1382. type := SyntaxTree.NewQualifiedType( position, parentScope, qualifiedIdentifier );
  1383. RETURN type
  1384. END;
  1385. recordScope := SyntaxTree.NewRecordScope(parentScope);
  1386. pointerType := SyntaxTree.NewPointerType(position,parentScope);
  1387. objectType := SyntaxTree.NewRecordType( position,parentScope,recordScope);
  1388. objectType.IsObject(TRUE);
  1389. objectType.SetPointerType(pointerType);
  1390. pointerType.SetPointerBase(objectType);
  1391. IF Optional(Scanner.LeftBrace) THEN
  1392. modifiers := Flags();
  1393. pointerType.SetModifiers(modifiers);
  1394. END;
  1395. IF Optional( Scanner.LeftParenthesis ) THEN
  1396. qualifiedIdentifier := QualifiedIdentifier();
  1397. baseType := SyntaxTree.NewQualifiedType(qualifiedIdentifier.position, parentScope, qualifiedIdentifier);
  1398. objectType.SetBaseType(baseType);
  1399. Check( Scanner.RightParenthesis )
  1400. END;
  1401. (*
  1402. IF Optional( Scanner.Implements ) THEN
  1403. REPEAT
  1404. qualifiedIdentifier := QualifiedIdentifier()
  1405. UNTIL ~Optional( Scanner.Comma );
  1406. END;
  1407. *)
  1408. IF Optional( Scanner.Semicolon ) THEN
  1409. (*Warning(token.position,Basic.InvalidCode,"no semicolon allowed here");*)
  1410. END;
  1411. DeclarationSequence( recordScope);
  1412. IF Peek(Scanner.Begin) OR Peek(Scanner.Code) THEN
  1413. recordScope.SetBodyProcedure(BodyProcedure(recordScope));
  1414. END;
  1415. Check(Scanner.End);
  1416. IF ExpectThisIdentifier( name ) THEN
  1417. (* check name not always, reflect in EBNF? *)
  1418. END;
  1419. IF Trace THEN E( "ObjectType" ) END;
  1420. RETURN pointerType
  1421. END ObjectType;
  1422. (** CellType = 'cell' [Flags] [PortList] [';'] {ImportList} DeclarationSequence [Body] 'end' [Identifier]
  1423. | 'object'. **)
  1424. PROCEDURE CellType(position: Position; name: SyntaxTree.Identifier; parentScope: SyntaxTree.Scope; isCellNet: BOOLEAN): SyntaxTree.Type;
  1425. VAR
  1426. cellType: SyntaxTree.CellType;
  1427. cellScope: SyntaxTree.CellScope;
  1428. modifiers: SyntaxTree.Modifier;
  1429. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
  1430. qualifiedType: SyntaxTree.Type;
  1431. BEGIN
  1432. IF Trace THEN S( "CellType" ) END;
  1433. (* token cell already consumed *)
  1434. cellScope := SyntaxTree.NewCellScope(parentScope);
  1435. cellType := SyntaxTree.NewCellType( position, parentScope,cellScope);
  1436. cellType.IsCellNet(isCellNet);
  1437. cellScope.SetOwnerCell(cellType);
  1438. IF Optional(Scanner.Colon) THEN
  1439. qualifiedIdentifier := QualifiedIdentifier();
  1440. qualifiedType := SyntaxTree.NewQualifiedType(qualifiedIdentifier.position, parentScope, qualifiedIdentifier );
  1441. cellType.SetBaseType( qualifiedType );
  1442. END;
  1443. IF Optional(Scanner.LeftBrace) THEN
  1444. modifiers := Flags();
  1445. cellType.SetModifiers(modifiers);
  1446. END;
  1447. IF Optional( Scanner.LeftParenthesis ) THEN
  1448. PortList(cellType,cellScope);
  1449. END;
  1450. IF Optional( Scanner.Semicolon ) THEN END;
  1451. WHILE Optional(Scanner.Import) DO ImportList(cellScope) END;
  1452. DeclarationSequence( cellScope);
  1453. IF Peek(Scanner.Begin) OR Peek(Scanner.Code) THEN
  1454. cellScope.SetBodyProcedure(BodyProcedure(cellScope));
  1455. END;
  1456. Check(Scanner.End);
  1457. IF ExpectThisIdentifier( name ) THEN
  1458. (* check name not always, reflect in EBNF? *)
  1459. END;
  1460. IF Trace THEN E( "CellType" ) END;
  1461. RETURN cellType
  1462. END CellType;
  1463. (** PointerType = 'pointer' [Flags] 'to' Type. **)
  1464. PROCEDURE PointerType( position: Position; parentScope: SyntaxTree.Scope ): SyntaxTree.PointerType;
  1465. VAR pointerType: SyntaxTree.PointerType; base: SyntaxTree.Type; modifiers: SyntaxTree.Modifier;
  1466. BEGIN
  1467. IF Trace THEN S( "PointerType" ) END;
  1468. (* pointer token already consumed *)
  1469. pointerType := SyntaxTree.NewPointerType( position ,parentScope);
  1470. IF Optional(Scanner.LeftBrace) THEN
  1471. modifiers := Flags();
  1472. pointerType.SetModifiers(modifiers)
  1473. END;
  1474. Check( Scanner.To );
  1475. base := Type(SyntaxTree.invalidIdentifier, parentScope);
  1476. pointerType.SetPointerBase( base );
  1477. IF base IS SyntaxTree.RecordType THEN
  1478. base(SyntaxTree.RecordType).SetPointerType(pointerType);
  1479. END;
  1480. IF Trace THEN E( "PointerType" ) END;
  1481. RETURN pointerType
  1482. END PointerType;
  1483. (**
  1484. RecordType = 'record' [Flags] ['(' QualifiedIdentifier ')'] [VariableDeclaration {';' VariableDeclaration}] 'end'.
  1485. **)
  1486. PROCEDURE RecordType(position: Position; parentScope:SyntaxTree.Scope ): SyntaxTree.RecordType;
  1487. VAR
  1488. recordType: SyntaxTree.RecordType;
  1489. recordScope: SyntaxTree.RecordScope;
  1490. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier; flags: SET; qualifiedType: SyntaxTree.QualifiedType;
  1491. modifier: SyntaxTree.Modifier;
  1492. BEGIN
  1493. IF Trace THEN S( "RecordType" ) END;
  1494. (* record token already consumed *)
  1495. flags := {};
  1496. recordScope := SyntaxTree.NewRecordScope(parentScope);
  1497. recordType := SyntaxTree.NewRecordType( position, parentScope, recordScope);
  1498. IF Optional( Scanner.LeftBrace ) THEN
  1499. modifier := Flags();
  1500. recordType.SetModifiers(modifier);
  1501. END;
  1502. IF Optional( Scanner.LeftParenthesis ) THEN
  1503. qualifiedIdentifier := QualifiedIdentifier();
  1504. qualifiedType := SyntaxTree.NewQualifiedType(qualifiedIdentifier.position, parentScope, qualifiedIdentifier );
  1505. recordType.SetBaseType( qualifiedType );
  1506. Check( Scanner.RightParenthesis )
  1507. END;
  1508. IF Lax THEN
  1509. WHILE Peek(Scanner.Identifier) DO VariableDeclaration(recordScope); Ignore(Scanner.Semicolon) END;
  1510. ELSE
  1511. REPEAT
  1512. IF Peek(Scanner.Identifier) THEN VariableDeclaration( recordScope ) END;
  1513. UNTIL ~Optional( Scanner.Semicolon );
  1514. END;
  1515. LOOP
  1516. IF Optional(Scanner.Procedure) THEN ProcedureDeclaration(recordScope); Ignore(Scanner.Semicolon);
  1517. ELSIF Optional(Scanner.Operator) THEN OperatorDeclaration(recordScope); Ignore(Scanner.Semicolon);
  1518. ELSE EXIT
  1519. END;
  1520. END;
  1521. (*WHILE Optional(Scanner.Procedure) DO ProcedureDeclaration(recordScope); Ignore(Scanner.Semicolon) END; *)
  1522. Check( Scanner.End );
  1523. IF Trace THEN E( "RecordType" ) END;
  1524. RETURN recordType
  1525. END RecordType;
  1526. (** ArrayType = 'array' 'of' Type | 'array' Expression {',' Expression} 'of' Type
  1527. | 'array' '[' MathArraySize {',' MathArraySize} ']' ['of' Type].
  1528. MathArraySize = Expression | '*' | '?'.
  1529. **)
  1530. PROCEDURE ArrayType(position: Position; parentScope: SyntaxTree.Scope ): SyntaxTree.Type;
  1531. VAR
  1532. arrayType: SyntaxTree.ArrayType;
  1533. type: SyntaxTree.Type;
  1534. base: SyntaxTree.Type;
  1535. expression: SyntaxTree.Expression;
  1536. modifiers: SyntaxTree.Modifier;
  1537. PROCEDURE MathArray(): SyntaxTree.Type;
  1538. VAR mathType: SyntaxTree.MathArrayType; base: SyntaxTree.Type;
  1539. BEGIN
  1540. IF Optional(Scanner.Questionmark) THEN
  1541. mathType := SyntaxTree.NewMathArrayType(position,parentScope, SyntaxTree.Tensor);
  1542. ELSIF Optional(Scanner.Times) THEN (* open array *)
  1543. mathType := SyntaxTree.NewMathArrayType(position,parentScope, SyntaxTree.Open);
  1544. ELSE (* size given *)
  1545. mathType := SyntaxTree.NewMathArrayType(position,parentScope, SyntaxTree.Static);
  1546. expression := Expression();
  1547. mathType.SetLength(expression);
  1548. END;
  1549. IF Optional(Scanner.Comma) THEN
  1550. base := MathArray()
  1551. ELSIF Mandatory(Scanner.RightBracket) THEN
  1552. IF Optional( Scanner.Of ) THEN
  1553. base := Type(SyntaxTree.invalidIdentifier , parentScope ); (* base type *)
  1554. END;
  1555. END;
  1556. mathType.SetModifiers(modifiers);
  1557. modifiers := NIL;
  1558. mathType.SetArrayBase(base);
  1559. RETURN mathType;
  1560. END MathArray;
  1561. BEGIN
  1562. IF Trace THEN S( "ArrayType" ) END;
  1563. (* array token already consumed *)
  1564. IF Optional(Scanner.LeftBrace) THEN
  1565. modifiers := Flags();
  1566. END;
  1567. IF Optional(Scanner.LeftBracket) THEN (* math array *)
  1568. type := MathArray();
  1569. ELSIF Optional( Scanner.Of ) THEN (* open array *)
  1570. arrayType := SyntaxTree.NewArrayType(position,parentScope, SyntaxTree.Open);
  1571. type := arrayType;
  1572. base := Type( SyntaxTree.invalidIdentifier ,parentScope);
  1573. arrayType.SetArrayBase( base )
  1574. ELSE (* static array *)
  1575. arrayType := SyntaxTree.NewArrayType(position,parentScope, SyntaxTree.Static);
  1576. type := arrayType;
  1577. expression := SimpleExpression();
  1578. arrayType.SetLength( expression );
  1579. position := token.position;
  1580. IF Optional( Scanner.Comma ) THEN
  1581. base := ArrayType( position,parentScope);
  1582. arrayType.SetArrayBase( base )
  1583. ELSIF Mandatory( Scanner.Of ) THEN
  1584. base := Type(SyntaxTree.invalidIdentifier , parentScope ); (* base type *)
  1585. arrayType.SetArrayBase( base );
  1586. END;
  1587. END;
  1588. IF modifiers # NIL THEN
  1589. Error(modifiers.position, Basic.InvalidCode, "forbidden modifiers");
  1590. END;
  1591. IF Trace THEN E( "ArrayType" ) END;
  1592. RETURN type
  1593. END ArrayType;
  1594. (** EnumerationType = 'enum' ['('QualifiedIdentifier')'] IdentifierDefinition ['=' Expression]
  1595. {',' IdentifierDefinition ['=' Expression]} 'end'. *)
  1596. PROCEDURE EnumerationType(position: Position; parentScope: SyntaxTree.Scope): SyntaxTree.Type;
  1597. VAR type: SyntaxTree.EnumerationType; scope: SyntaxTree.EnumerationScope; identifier: SyntaxTree.Identifier;
  1598. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier; qualifiedType: SyntaxTree.QualifiedType; access: SET;
  1599. constant: SyntaxTree.Constant; expression: SyntaxTree.Expression;
  1600. BEGIN
  1601. (* enum token already consumed *)
  1602. scope := SyntaxTree.NewEnumerationScope(parentScope);
  1603. type := SyntaxTree.NewEnumerationType(position,parentScope, scope);
  1604. IF Optional( Scanner.LeftParenthesis ) THEN
  1605. qualifiedIdentifier := QualifiedIdentifier();
  1606. qualifiedType := SyntaxTree.NewQualifiedType(qualifiedIdentifier.position, parentScope, qualifiedIdentifier );
  1607. type.SetEnumerationBase( qualifiedType );
  1608. Check( Scanner.RightParenthesis )
  1609. END;
  1610. REPEAT
  1611. IdentifierDefinition(identifier,access,FALSE);
  1612. position := token.position;
  1613. constant := SyntaxTree.NewConstant( position, identifier );
  1614. CommentSymbol(constant);
  1615. constant.SetAccess(access);
  1616. IF Optional(Scanner.Equal) THEN
  1617. expression := Expression();
  1618. constant.SetValue( expression );
  1619. END;
  1620. scope.AddConstant( constant );
  1621. UNTIL ~Optional(Scanner.Comma);
  1622. IF Mandatory(Scanner.End) THEN END;
  1623. RETURN type
  1624. END EnumerationType;
  1625. (** PortType = 'port' ('in'|'out') ['(' Expression ')'] *)
  1626. PROCEDURE PortType(position: Position; parentScope: SyntaxTree.Scope): SyntaxTree.Type;
  1627. VAR type: SyntaxTree.Type; direction: LONGINT; sizeExpression: SyntaxTree.Expression;
  1628. BEGIN
  1629. (* port token already consumed *)
  1630. IF Optional(Scanner.In) THEN
  1631. direction := SyntaxTree.InPort
  1632. ELSIF Optional(Scanner.Out) THEN
  1633. direction := SyntaxTree.OutPort
  1634. ELSE
  1635. Error(position,Basic.InvalidCode,"invalid direction, expected IN or OUT");
  1636. END;
  1637. IF Optional(Scanner.LeftParenthesis) THEN
  1638. sizeExpression := Expression();
  1639. IF Mandatory(Scanner.RightParenthesis )THEN END;
  1640. END;
  1641. type := SyntaxTree.NewPortType(position, direction, sizeExpression, parentScope);
  1642. RETURN type
  1643. END PortType;
  1644. (** Type = ArrayType | RecordType | PointerType | ObjectType | CellType | CellnetType | PortType
  1645. | ProcedureType | EnumerationType | QualifiedIdentifier. *)
  1646. PROCEDURE Type( name: SyntaxTree.Identifier; parentScope: SyntaxTree.Scope ): SyntaxTree.Type;
  1647. VAR type: SyntaxTree.Type; qualifiedIdentifier: SyntaxTree.QualifiedIdentifier; position: Position;
  1648. BEGIN
  1649. IF Trace THEN S( "Type" ) END;
  1650. position := token.position;
  1651. IF Optional( Scanner.Array ) THEN type := ArrayType( position,parentScope );
  1652. ELSIF Optional( Scanner.Record ) THEN type := RecordType( position,parentScope );
  1653. ELSIF Optional( Scanner.Pointer ) THEN type := PointerType( position,parentScope );
  1654. ELSIF Optional( Scanner.Object ) THEN type := ObjectType( position,name,parentScope );
  1655. ELSIF Optional( Scanner.Cell) THEN type := CellType( position, name, parentScope,FALSE);
  1656. ELSIF Optional( Scanner.CellNet) THEN type := CellType( position, name, parentScope, TRUE);
  1657. ELSIF Optional( Scanner.Port) THEN type := PortType( position, parentScope)
  1658. ELSIF Optional( Scanner.Procedure ) THEN type := ProcedureType( position,parentScope);
  1659. ELSIF Optional( Scanner.Enum ) THEN type := EnumerationType( position,parentScope);
  1660. ELSIF (Symbol() = Scanner.Address) OR (Symbol() = Scanner.Size) THEN
  1661. qualifiedIdentifier := SyntaxTree.NewQualifiedIdentifier(position,SyntaxTree.invalidIdentifier, token.identifier);
  1662. type := SyntaxTree.NewQualifiedType( qualifiedIdentifier.position, parentScope, qualifiedIdentifier );
  1663. NextToken;
  1664. ELSE qualifiedIdentifier := QualifiedIdentifier();
  1665. type := SyntaxTree.NewQualifiedType( qualifiedIdentifier.position, parentScope, qualifiedIdentifier );
  1666. END;
  1667. IF Trace THEN E( "Type" ) END;
  1668. RETURN type
  1669. END Type;
  1670. (** PortDeclaration = Identifier [Flags] {',' Identifier [Flags]}':' Type. **)
  1671. PROCEDURE PortDeclaration(cell: SyntaxTree.CellType; parentScope: SyntaxTree.Scope);
  1672. VAR
  1673. type: SyntaxTree.Type; name: SyntaxTree.Identifier;
  1674. firstParameter, parameter: SyntaxTree.Parameter;
  1675. position: Position; modifiers: SyntaxTree.Modifier;
  1676. BEGIN
  1677. IF Trace THEN S( "PortDeclaration" ) END;
  1678. firstParameter := cell.lastParameter;
  1679. REPEAT
  1680. name := Identifier(position);
  1681. parameter := SyntaxTree.NewParameter(position,cell,name,SyntaxTree.ValueParameter);
  1682. cell.AddParameter(parameter);
  1683. IF Optional(Scanner.LeftBrace) THEN
  1684. modifiers := Flags();
  1685. parameter.SetModifiers(modifiers);
  1686. END;
  1687. UNTIL ~Optional( Scanner.Comma );
  1688. Check( Scanner.Colon );
  1689. type := Type( SyntaxTree.invalidIdentifier, parentScope);
  1690. ASSERT(type # NIL);
  1691. IF firstParameter # NIL THEN parameter := firstParameter.nextParameter ELSE parameter := cell.firstParameter END;
  1692. WHILE parameter # NIL DO
  1693. parameter.SetType( type );
  1694. parameter := parameter.nextParameter;
  1695. END;
  1696. IF Trace THEN E( "PortDeclaration" )
  1697. END;
  1698. END PortDeclaration;
  1699. (** PortList = '(' [PortDeclaration {';' PortDeclaration}] ')'. **)
  1700. PROCEDURE PortList( cell: SyntaxTree.CellType ; parentScope: SyntaxTree.Scope);
  1701. BEGIN
  1702. IF Trace THEN S( "PortList" ) END;
  1703. (* left parenthesis already consumed *)
  1704. IF ~Optional( Scanner.RightParenthesis ) THEN
  1705. IF Lax THEN
  1706. WHILE Peek(Scanner.Identifier) OR Peek(Scanner.Var) OR Peek(Scanner.Const) DO PortDeclaration( cell, parentScope ); Ignore(Scanner.Semicolon) END;
  1707. ELSE
  1708. REPEAT PortDeclaration( cell, parentScope ); UNTIL ~Optional( Scanner.Semicolon );
  1709. END;
  1710. Check( Scanner.RightParenthesis );
  1711. END;
  1712. IF Trace THEN E( "PortList" ) END;
  1713. END PortList;
  1714. (** ParameterDeclaration = ['var'|'const'] Identifier [Flags] ['= Expression] {',' Identifier [Flags] ['= Expression]}':' Type.**)
  1715. PROCEDURE ParameterDeclaration( procedureType: SyntaxTree.ProcedureType ; parentScope: SyntaxTree.Scope);
  1716. VAR
  1717. type: SyntaxTree.Type; name: SyntaxTree.Identifier;
  1718. firstParameter, parameter: SyntaxTree.Parameter; kind: LONGINT; position: Position;
  1719. BEGIN
  1720. IF Trace THEN S( "ParameterDeclaration" ) END;
  1721. IF Optional( Scanner.Var ) THEN (* var parameter *)
  1722. kind := SyntaxTree.VarParameter
  1723. ELSIF Optional( Scanner.Const ) THEN (* const parameter *)
  1724. kind := SyntaxTree.ConstParameter
  1725. ELSIF Symbol() # Scanner.Identifier THEN
  1726. Error(token.position,Scanner.Identifier,"");
  1727. RETURN
  1728. ELSE kind := SyntaxTree.ValueParameter
  1729. END;
  1730. firstParameter := procedureType.lastParameter;
  1731. REPEAT
  1732. name := Identifier(position);
  1733. parameter := SyntaxTree.NewParameter(position,procedureType,name,kind);
  1734. IF Optional(Scanner.LeftBrace) THEN parameter.SetModifiers(Flags()) END;
  1735. procedureType.AddParameter(parameter);
  1736. IF Optional(Scanner.Equal) THEN
  1737. parameter.SetDefaultValue(Expression());
  1738. END
  1739. UNTIL ~Optional( Scanner.Comma );
  1740. Check( Scanner.Colon );
  1741. type := Type( SyntaxTree.invalidIdentifier, parentScope);
  1742. CommentSymbol(parameter);
  1743. ASSERT(type # NIL);
  1744. IF firstParameter # NIL THEN parameter := firstParameter.nextParameter ELSE parameter := procedureType.firstParameter END;
  1745. WHILE parameter # NIL DO
  1746. parameter.SetType( type );
  1747. parameter := parameter.nextParameter;
  1748. END;
  1749. IF Trace THEN E( "ParameterDeclaration" )
  1750. END;
  1751. END ParameterDeclaration;
  1752. (** FormalParameters = '(' [ParameterDeclaration {';' ParameterDeclaration}] ')' [':' [Flags] Type]. **)
  1753. PROCEDURE FormalParameters( procedureType: SyntaxTree.ProcedureType ; parentScope: SyntaxTree.Scope);
  1754. VAR type: SyntaxTree.Type; position: Position;
  1755. BEGIN
  1756. IF Trace THEN S( "FormalParameters" ) END;
  1757. (* left parenthesis already consumed *)
  1758. IF ~Optional( Scanner.RightParenthesis ) THEN
  1759. IF Lax THEN
  1760. WHILE Peek(Scanner.Identifier) OR Peek(Scanner.Const) OR Peek(Scanner.Var) DO
  1761. ParameterDeclaration(procedureType, parentScope); Ignore(Scanner.Semicolon)
  1762. END;
  1763. ELSE
  1764. REPEAT ParameterDeclaration( procedureType, parentScope ); UNTIL ~Optional( Scanner.Semicolon );
  1765. END;
  1766. Check( Scanner.RightParenthesis );
  1767. END;
  1768. IF Optional( Scanner.Colon ) THEN
  1769. position:= token.position;
  1770. IF Optional( Scanner.LeftBrace) THEN
  1771. procedureType.SetReturnTypeModifiers(Flags());
  1772. END;
  1773. type := Type(SyntaxTree.invalidIdentifier,parentScope);
  1774. (* formally, any type is permitted as return type. Actually some of them might simply not be usable *)
  1775. procedureType.SetReturnType(type);
  1776. END;
  1777. IF Trace THEN E( "FormalParameters" ) END;
  1778. END FormalParameters;
  1779. (** Flags = '{' [Identifier ['(' Expression ')'|'=' Expression] {',' Identifier ['(' Expression ')' | '=' Expression ] } ] '}'. **)
  1780. PROCEDURE Flags(): SyntaxTree.Modifier;
  1781. VAR identifier: SyntaxTree.Identifier; modifier,list: SyntaxTree.Modifier; position: Position; expression: SyntaxTree.Expression;
  1782. BEGIN
  1783. IF Trace THEN S( "Flags" ) END;
  1784. (* left brace already consumed *)
  1785. list := NIL;
  1786. IF Peek(Scanner.RightBrace) THEN (* empty flags *)
  1787. ELSE
  1788. REPEAT
  1789. position := token.position;
  1790. identifier := Identifier(position);
  1791. IF Optional(Scanner.LeftParenthesis) THEN
  1792. expression := Expression();
  1793. Check(Scanner.RightParenthesis)
  1794. ELSIF Optional(Scanner.Equal) THEN
  1795. expression := Expression();
  1796. ELSE
  1797. expression := NIL
  1798. END;
  1799. modifier := SyntaxTree.NewModifier(position,identifier,expression);
  1800. AppendModifier(list,modifier);
  1801. UNTIL ~Optional( Scanner.Comma ) & ~Optional(Scanner.Semicolon);
  1802. END;
  1803. Check(Scanner.RightBrace);
  1804. IF Trace THEN E( "Flags" ) END;
  1805. RETURN list;
  1806. END Flags;
  1807. PROCEDURE SetNextInComment(c: SyntaxTree.Comment; this: ANY);
  1808. BEGIN
  1809. WHILE c # NIL DO
  1810. c.SetItem(this,FALSE);
  1811. c := c.nextComment
  1812. END;
  1813. END SetNextInComment;
  1814. PROCEDURE CommentSymbol(symbol: SyntaxTree.Symbol);
  1815. BEGIN
  1816. IF (recentComment # NIL) (* & (recentComment.nextSymbol = NIL) *) THEN
  1817. symbol.SetComment(recentComment);
  1818. SetNextInComment(recentComment, symbol);
  1819. recentComment := NIL
  1820. END;
  1821. recentLine := scanner.position.line;
  1822. recentCommentItem := symbol;
  1823. END CommentSymbol;
  1824. PROCEDURE CommentStatement(symbol: SyntaxTree.Statement);
  1825. BEGIN
  1826. IF (recentComment # NIL) (* & (recentComment.nextSymbol = NIL) *) THEN
  1827. symbol.SetComment(recentComment);
  1828. SetNextInComment(recentComment, symbol);
  1829. recentComment := NIL
  1830. END;
  1831. recentLine := scanner.position.line;
  1832. recentCommentItem := symbol
  1833. END CommentStatement;
  1834. PROCEDURE CommentCasePart(symbol: SyntaxTree.CasePart);
  1835. BEGIN
  1836. IF (recentComment # NIL) (* & (recentComment.nextSymbol = NIL) *) THEN
  1837. symbol.SetComment(recentComment);
  1838. SetNextInComment(recentComment, symbol);
  1839. recentComment := NIL
  1840. END;
  1841. recentLine := scanner.position.line;
  1842. recentCommentItem := symbol
  1843. END CommentCasePart;
  1844. PROCEDURE CommentIfPart(symbol: SyntaxTree.IfPart);
  1845. BEGIN
  1846. IF (recentComment # NIL) (* & (recentComment.nextSymbol = NIL) *) THEN
  1847. symbol.SetComment(recentComment);
  1848. SetNextInComment(recentComment, symbol);
  1849. recentComment := NIL
  1850. END;
  1851. recentLine := scanner.position.line;
  1852. recentCommentItem := symbol
  1853. END CommentIfPart;
  1854. PROCEDURE CommentWithPart(symbol: SyntaxTree.WithPart);
  1855. BEGIN
  1856. IF (recentComment # NIL) (* & (recentComment.nextSymbol = NIL) *) THEN
  1857. symbol.SetComment(recentComment);
  1858. SetNextInComment(recentComment, symbol);
  1859. recentComment := NIL
  1860. END;
  1861. recentLine := scanner.position.line;
  1862. recentCommentItem := symbol
  1863. END CommentWithPart;
  1864. (** ProcedureDeclaration = 'procedure' ['^'|'&'|'~'|'-'|Flags ['-']] IdentifierDefinition [FormalParameters]';'
  1865. DeclarationSequence [Body] 'end' Identifier.
  1866. Forward declarations ignored.
  1867. **)
  1868. PROCEDURE ProcedureDeclaration( parentScope: SyntaxTree.Scope);
  1869. VAR name: SyntaxTree.Identifier;
  1870. procedure: SyntaxTree.Procedure;
  1871. procedureType: SyntaxTree.ProcedureType;
  1872. procedureScope : SyntaxTree.ProcedureScope;
  1873. access: SET;
  1874. position: Position;
  1875. isConstructor: BOOLEAN;
  1876. isFinalizer: BOOLEAN;
  1877. isInline: BOOLEAN;
  1878. modifiers: SyntaxTree.Modifier;
  1879. forwardDeclaration: BOOLEAN;
  1880. string: Scanner.StringType;
  1881. parameter: SyntaxTree.Parameter;
  1882. qualifiedIdentifier : SyntaxTree.QualifiedIdentifier;
  1883. identifier: SyntaxTree.Identifier;
  1884. kind: LONGINT;
  1885. BEGIN
  1886. IF Trace THEN S( "Procedure" ) END;
  1887. (* procedure symbol has already been consumed *)
  1888. modifiers := NIL;
  1889. isConstructor := FALSE; isFinalizer := FALSE; isInline := FALSE;
  1890. procedureType := SyntaxTree.NewProcedureType(token.position, parentScope);
  1891. position := token.position;
  1892. IF Optional( Scanner.Arrow) THEN (* ignore forward declarations *)
  1893. forwardDeclaration := TRUE;
  1894. ELSE forwardDeclaration := FALSE;
  1895. END;
  1896. IF Optional( Scanner.And ) THEN (* constructor *)
  1897. isConstructor := TRUE
  1898. ELSIF Optional( Scanner.Not ) THEN (* finalizer *)
  1899. isFinalizer := TRUE
  1900. ELSIF Optional( Scanner.Minus ) THEN (* inline *)
  1901. isInline := TRUE;
  1902. ELSIF Optional( Scanner.LeftBrace) THEN
  1903. modifiers := Flags();
  1904. IF Optional( Scanner.Minus ) THEN (* inline *)
  1905. isInline := TRUE
  1906. END;
  1907. END;
  1908. IF Peek(Scanner.String) OR Peek(Scanner.Character) THEN (* for compatibility with release *)
  1909. Error (position, Basic.InvalidCode, "Invalid operator declaration: replace 'procedure' by 'operator' keyword!");
  1910. OperatorDeclaration( parentScope );
  1911. RETURN
  1912. END;
  1913. procedureScope := SyntaxTree.NewProcedureScope(parentScope);
  1914. IF Optional(Scanner.LeftParenthesis) THEN (* type bound *)
  1915. IF Optional(Scanner.Var) THEN
  1916. kind := SyntaxTree.VarParameter
  1917. ELSIF Optional(Scanner.Const) THEN
  1918. kind := SyntaxTree.ConstParameter;
  1919. ELSE
  1920. kind := SyntaxTree.ConstParameter;
  1921. END;
  1922. identifier := Identifier(position);
  1923. parameter := SyntaxTree.NewParameter(position, procedureType, identifier, kind);
  1924. Check(Scanner.Colon);
  1925. qualifiedIdentifier := SyntaxTree.NewQualifiedIdentifier(position, SyntaxTree.invalidIdentifier, Identifier(position));
  1926. parameter.SetType(SyntaxTree.NewQualifiedType(position, procedureScope, qualifiedIdentifier));
  1927. Check(Scanner.RightParenthesis);
  1928. procedureType.SetSelfParameter(parameter);
  1929. parameter.SetSelfParameter(TRUE);
  1930. END;
  1931. position:= token.position;
  1932. IdentifierDefinition( name, access,TRUE);
  1933. procedure := SyntaxTree.NewProcedure( position, name, procedureScope);
  1934. procedure.SetConstructor(isConstructor);
  1935. procedure.SetFinalizer(isFinalizer);
  1936. procedure.SetInline(isInline);
  1937. CommentSymbol(procedure);
  1938. procedure.SetAccess(access);
  1939. procedureType.SetModifiers(modifiers);
  1940. procedure.SetType(procedureType);
  1941. IF Optional(Scanner.Extern) & MandatoryString(string) THEN procedure.SetExternalName(string); END;
  1942. IF Optional(Scanner.LeftParenthesis) THEN FormalParameters( procedureType, procedureScope) END;
  1943. IF (procedure.externalName = NIL) & ~forwardDeclaration THEN
  1944. IF Lax THEN Ignore(Scanner.Semicolon) ELSE Check( Scanner.Semicolon ) END;
  1945. DeclarationSequence( procedureScope);
  1946. IF Peek(Scanner.Begin) OR Peek(Scanner.Code) THEN
  1947. procedureScope.SetBody(Body(procedureScope));
  1948. END;
  1949. Check(Scanner.End);
  1950. IF ExpectThisIdentifier( name ) THEN END;
  1951. END;
  1952. parentScope.AddProcedureDeclaration( procedure );
  1953. IF Trace THEN E( "Procedure") END;
  1954. END ProcedureDeclaration;
  1955. (** OperatorDeclaration = 'operator' [Flags] ['-'] String ['*'|'-'] FormalParameters ';'
  1956. DeclarationSequence [Body] 'end' String.
  1957. **)
  1958. PROCEDURE OperatorDeclaration(parentScope: SyntaxTree.Scope );
  1959. VAR
  1960. string: Scanner.StringType;
  1961. procedureScope: SyntaxTree.ProcedureScope;
  1962. procedureType: SyntaxTree.ProcedureType;
  1963. operator: SyntaxTree.Operator;
  1964. access: SET;
  1965. i: LONGINT; position: Position;
  1966. modifiers: SyntaxTree.Modifier; (* nopov *)
  1967. isInline, forward: BOOLEAN;
  1968. BEGIN
  1969. IF Trace THEN S( "Operator" ) END;
  1970. (* token operator already consumed *)
  1971. position := token.position;
  1972. forward := Optional(Scanner.Arrow);
  1973. isInline := FALSE;
  1974. IF Optional( Scanner.LeftBrace) THEN
  1975. modifiers := Flags();
  1976. END;
  1977. IF Optional( Scanner.Minus ) THEN (* inline *)
  1978. isInline := TRUE;
  1979. END;
  1980. IF MandatoryString( string ) THEN
  1981. (* copy string to name and check for length. LEN(name)>0, LEN(string)>0 can be presumed *)
  1982. i := 0; WHILE (string^[i] # 0X) DO INC(i) END;
  1983. IF i >= Scanner.MaxIdentifierLength THEN (* string too long to act as operator identifier *)
  1984. Error(token.position,Basic.StringTooLong,"");
  1985. END
  1986. END;
  1987. IF Optional( Scanner.Times ) THEN access := SyntaxTree.ReadOnly;
  1988. ELSIF Optional( Scanner.Minus ) THEN access := SyntaxTree.ReadOnly;
  1989. ELSE access := SyntaxTree.Internal;
  1990. END;
  1991. procedureScope := SyntaxTree.NewProcedureScope(parentScope);
  1992. operator := SyntaxTree.NewOperator( token.position, SyntaxTree.NewIdentifier(string^), procedureScope);
  1993. CommentSymbol(operator);
  1994. operator.SetAccess(access);
  1995. procedureType := SyntaxTree.NewProcedureType(token.position,parentScope);
  1996. IF Mandatory(Scanner.LeftParenthesis) THEN FormalParameters( procedureType, procedureScope ) END;
  1997. procedureType.SetModifiers(modifiers); (* nopov *)
  1998. operator.SetType( procedureType );
  1999. operator.SetInline(isInline);
  2000. IF Lax THEN Ignore(Scanner.Semicolon) ELSE Check( Scanner.Semicolon ) END;
  2001. IF ~forward THEN
  2002. DeclarationSequence( procedureScope );
  2003. IF Peek(Scanner.Begin) OR Peek(Scanner.Code) THEN
  2004. procedureScope.SetBody(Body(procedureScope));
  2005. END;
  2006. IF Mandatory(Scanner.End) & ExpectThisString(string^) THEN END;
  2007. END;
  2008. parentScope.AddProcedureDeclaration(operator);
  2009. IF parentScope IS SyntaxTree.ModuleScope THEN
  2010. parentScope(SyntaxTree.ModuleScope).AddOperator(operator);
  2011. ELSIF parentScope IS SyntaxTree.RecordScope THEN
  2012. parentScope(SyntaxTree.RecordScope).AddOperator(operator);
  2013. ELSE
  2014. Error(position,Basic.InvalidCode,"Operators only allowed in module or record scope"); (* nopov *)
  2015. END;
  2016. IF Trace THEN EE( "Operator", string^ ) END;
  2017. END OperatorDeclaration;
  2018. (** VariableNameList = IdentifierDefinition [Flags] [':=' Expression | 'extern' String] {',' IdentifierDefinition [Flags] [':=' Expression | 'extern' String] }.**)
  2019. PROCEDURE VariableNameList( scope: SyntaxTree.Scope );
  2020. VAR varname: SyntaxTree.Identifier; position: Position; variable: SyntaxTree.Variable; flags,access: SET; string: Scanner.StringType;
  2021. BEGIN
  2022. IF Trace THEN S( "VariableNameList" ) END;
  2023. REPEAT
  2024. flags := {};
  2025. position := token.position;
  2026. IdentifierDefinition( varname, access,TRUE);
  2027. variable := SyntaxTree.NewVariable( position, varname );
  2028. CommentSymbol(variable);
  2029. IF Optional(Scanner.LeftBrace) THEN variable.SetModifiers(Flags()) END;
  2030. IF Optional(Scanner.Becomes) THEN variable.SetInitializer (Expression());
  2031. ELSIF Optional(Scanner.Extern) & MandatoryString(string) THEN variable.SetExternalName(string); END;
  2032. variable.SetAccess(access);
  2033. scope.AddVariable(variable);
  2034. UNTIL ~Optional( Scanner.Comma );
  2035. IF Trace THEN E( "VariableNameList" ) END;
  2036. END VariableNameList;
  2037. (** VariableDeclaration = VariableNameList ':' Type. **)
  2038. PROCEDURE VariableDeclaration(parentScope: SyntaxTree.Scope );
  2039. VAR
  2040. variable, firstVariable: SyntaxTree.Variable; type: SyntaxTree.Type;
  2041. BEGIN
  2042. IF Trace THEN S( "VariableDeclaration" ) END;
  2043. firstVariable := parentScope.lastVariable;
  2044. VariableNameList( parentScope );
  2045. Check( Scanner.Colon );
  2046. type := Type( SyntaxTree.invalidIdentifier, parentScope );
  2047. variable := firstVariable;
  2048. IF firstVariable # NIL THEN variable := firstVariable.nextVariable ELSE variable := parentScope.firstVariable END;
  2049. WHILE variable # NIL DO
  2050. variable.SetType( type );
  2051. variable := variable.nextVariable;
  2052. END;
  2053. IF Trace THEN E( "VariableDeclaration" ) END;
  2054. END VariableDeclaration;
  2055. (** TypeDeclaration = IdentifierDefinition '=' Type.**)
  2056. PROCEDURE TypeDeclaration(parentScope: SyntaxTree.Scope);
  2057. VAR name: SyntaxTree.Identifier; position: Position; type: SyntaxTree.Type; typeDeclaration: SyntaxTree.TypeDeclaration; access: SET;
  2058. BEGIN
  2059. IF Trace THEN S( "TypeDeclaration" ) END;
  2060. position := token.position;
  2061. IdentifierDefinition( name, access,FALSE);
  2062. typeDeclaration := SyntaxTree.NewTypeDeclaration( position,name);
  2063. CommentSymbol(typeDeclaration);
  2064. Check( Scanner.Equal );
  2065. type := Type( name , parentScope);
  2066. type.SetTypeDeclaration(typeDeclaration);
  2067. typeDeclaration.SetDeclaredType(type);
  2068. (*
  2069. type.SetName(typeDeclaration.name); (* don't do that: overwrites global names ! *)
  2070. *)
  2071. typeDeclaration.SetAccess(access);
  2072. parentScope.AddTypeDeclaration( typeDeclaration );
  2073. IF Trace THEN E( "TypeDeclaration" ) END;
  2074. END TypeDeclaration;
  2075. (** ConstDeclaration = IdentifierDefinition '=' Expression. **)
  2076. PROCEDURE ConstDeclaration(parentScope: SyntaxTree.Scope );
  2077. VAR name: SyntaxTree.Identifier; position: Position; constant: SyntaxTree.Constant; expression: SyntaxTree.Expression; access: SET;
  2078. BEGIN
  2079. IF Trace THEN S( "ConstDeclaration" ) END;
  2080. IdentifierDefinition( name, access, FALSE);
  2081. position := token.position;
  2082. constant := SyntaxTree.NewConstant( position, name );
  2083. CommentSymbol(constant);
  2084. constant.SetAccess(access);
  2085. Check( Scanner.Equal );
  2086. expression := Expression();
  2087. constant.SetValue( expression );
  2088. parentScope.AddConstant( constant );
  2089. IF Trace THEN E( "ConstDeclaration" ) END;
  2090. END ConstDeclaration;
  2091. (** DeclarationSequence = { 'const' [ConstDeclaration] {';' [ConstDeclaration]}
  2092. |'type' [TypeDeclaration] {';' [TypeDeclaration]}
  2093. |'var' [VariableDeclaration] {';' [VariableDeclaration]}
  2094. | ProcedureDeclaration
  2095. | OperatorDeclaration
  2096. | ';'
  2097. }
  2098. **)
  2099. PROCEDURE DeclarationSequence( parentScope: SyntaxTree.Scope);
  2100. VAR previousScope: SyntaxTree.Scope;
  2101. BEGIN
  2102. previousScope := currentScope;
  2103. currentScope := parentScope;
  2104. IF Trace THEN S( "DeclarationSequence" ) END;
  2105. IF Lax THEN
  2106. LOOP
  2107. Ignore(Scanner.Semicolon);
  2108. IF Optional(Scanner.Const) THEN
  2109. WHILE Peek(Scanner.Identifier) DO ConstDeclaration(parentScope); Ignore(Scanner.Semicolon) END;
  2110. ELSIF Optional(Scanner.Type) THEN
  2111. WHILE Peek(Scanner.Identifier) DO TypeDeclaration(parentScope); Ignore(Scanner.Semicolon) END;
  2112. ELSIF Optional(Scanner.Var) THEN
  2113. WHILE Peek(Scanner.Identifier) DO VariableDeclaration(parentScope); Ignore(Scanner.Semicolon); END;
  2114. ELSIF Optional(Scanner.Procedure) THEN
  2115. ProcedureDeclaration(parentScope); Ignore(Scanner.Semicolon)
  2116. ELSIF Optional(Scanner.Operator) THEN
  2117. OperatorDeclaration(parentScope); Ignore(Scanner.Semicolon);
  2118. ELSE
  2119. EXIT
  2120. END;
  2121. END;
  2122. ELSE
  2123. LOOP
  2124. IF Optional( Scanner.Const ) THEN
  2125. REPEAT
  2126. IF Peek(Scanner.Identifier) THEN ConstDeclaration( parentScope ) END
  2127. UNTIL ~Optional( Scanner.Semicolon )
  2128. ELSIF Optional( Scanner.Type ) THEN
  2129. REPEAT
  2130. IF Peek(Scanner.Identifier) THEN TypeDeclaration( parentScope) END
  2131. UNTIL ~Optional( Scanner.Semicolon )
  2132. ELSIF Optional( Scanner.Var ) THEN
  2133. REPEAT
  2134. IF Peek(Scanner.Identifier) THEN VariableDeclaration( parentScope ) END
  2135. UNTIL ~Optional( Scanner.Semicolon )
  2136. ELSIF Optional(Scanner.Operator) THEN
  2137. OperatorDeclaration( parentScope);
  2138. ELSIF Optional( Scanner.Procedure ) THEN
  2139. ProcedureDeclaration( parentScope );
  2140. ELSE EXIT
  2141. END;
  2142. Ignore(Scanner.Semicolon)
  2143. END;
  2144. END;
  2145. currentScope := previousScope;
  2146. IF Trace THEN E( "DeclarationSequence" ) END;
  2147. END DeclarationSequence;
  2148. (**
  2149. ImportList = 'import' Import { ',' Import } ';'.
  2150. Import = Identifier [':=' Identifier] ['in' Identifier].
  2151. **)
  2152. PROCEDURE ImportList( scope: SyntaxTree.Scope );
  2153. VAR alias, name, context: SyntaxTree.Identifier; import: SyntaxTree.Import; position, idPosition: Position; aliased: BOOLEAN;
  2154. BEGIN
  2155. IF Trace THEN S( "ImportList" ) END;
  2156. (* import token already consumed *)
  2157. REPEAT
  2158. alias := Identifier(idPosition);
  2159. position := token.position;
  2160. IF alias # SyntaxTree.invalidIdentifier THEN
  2161. aliased := Optional( Scanner.Becomes );
  2162. IF aliased THEN name := Identifier(idPosition) ELSE name := alias END;
  2163. import := SyntaxTree.NewImport( position, alias, name, TRUE );
  2164. CommentSymbol(import);
  2165. IF Optional(Scanner.In) THEN
  2166. position := token.position;
  2167. context := Identifier(idPosition);
  2168. IF context # SyntaxTree.invalidIdentifier THEN import.SetContext(context) END;
  2169. ELSIF aliased & (name = alias) THEN
  2170. Basic.Warning(diagnostics, scanner.source^, position, "duplicated import alias");
  2171. END;
  2172. WITH scope:
  2173. SyntaxTree.ModuleScope DO
  2174. scope.AddImport( import );
  2175. | SyntaxTree.CellScope DO
  2176. scope.AddImport( import );
  2177. END;
  2178. END;
  2179. UNTIL ~Optional( Scanner.Comma );
  2180. IF Lax THEN Ignore(Scanner.Semicolon) ELSE Check( Scanner.Semicolon ) END;
  2181. IF Trace THEN E( "ImportList" ); END;
  2182. END ImportList;
  2183. (** Module = ('module' | 'cellnet' [Flags]) Identifier ['in' Identifier]';'
  2184. {ImportList} DeclarationSequence [Body]
  2185. 'end' Identifier '.'.
  2186. **)
  2187. PROCEDURE Module*(): SyntaxTree.Module;
  2188. VAR moduleName, context: SyntaxTree.Identifier; module: SyntaxTree.Module; position: Position; isCellNet: BOOLEAN;
  2189. scannerDiagnostics: Diagnostics.Diagnostics; modifiers: SyntaxTree.Modifier; (* c: SyntaxTree.Comment; *)
  2190. BEGIN
  2191. IF Trace THEN S( "Module" ) END;
  2192. position := token.position;
  2193. moduleScope := SyntaxTree.NewModuleScope(); (* needed to feed in comment already before module starts *)
  2194. currentScope := moduleScope;
  2195. isCellNet := Optional(Scanner.CellNet);
  2196. IF isCellNet OR Mandatory( Scanner.Module ) THEN
  2197. (*c := recentComment; recentComment := NIL;*)
  2198. IF isCellNet & Optional(Scanner.LeftBrace) THEN modifiers := Flags() ELSE modifiers := NIL END;
  2199. moduleName := Identifier(position);
  2200. module := SyntaxTree.NewModule( scanner.source^, position, moduleName, moduleScope, scanner.case );
  2201. CommentSymbol(module);
  2202. (*
  2203. module.SetComment(c);
  2204. SetNextInComment(c, module);
  2205. *)
  2206. IF isCellNet THEN module.SetCellNet(TRUE); module.SetModifiers(modifiers); END;
  2207. module.SetType(SyntaxTree.moduleType);
  2208. IF Optional(Scanner.In) THEN
  2209. position := token.position;
  2210. context := Identifier(position);
  2211. module.SetContext(context);
  2212. END;
  2213. IF Lax THEN Ignore(Scanner.Semicolon) ELSE Check(Scanner.Semicolon) END;
  2214. IF ~Peek(Scanner.EndOfText) THEN
  2215. module.SetClosingComment(recentComment);
  2216. SetNextInComment(recentComment, module);
  2217. recentComment := NIL;
  2218. END;
  2219. WHILE Optional(Scanner.Import) DO ImportList(moduleScope) END;
  2220. DeclarationSequence( moduleScope);
  2221. IF Peek(Scanner.Begin) OR Peek(Scanner.Code) THEN
  2222. moduleScope.SetBodyProcedure(BodyProcedure(moduleScope)); (* insert empty body procedure if necessary *)
  2223. END;
  2224. Check(Scanner.End);
  2225. IF ExpectThisIdentifier( moduleName ) THEN
  2226. IF Symbol() # Scanner.Period THEN
  2227. Error( token.position, Scanner.Period, "" )
  2228. ELSIF ~error & ~scanner.error THEN (* read ahead to read comments and to check for next module *)
  2229. scanner.ResetCase;
  2230. scannerDiagnostics := NIL;
  2231. scanner.ResetErrorDiagnostics(scannerDiagnostics);
  2232. NextToken;
  2233. scanner.ResetErrorDiagnostics(scannerDiagnostics);
  2234. END;
  2235. (*
  2236. (* do not use Check for not reading after end of module *)
  2237. IF ~Peek(Scanner.Module) & ~Peek(Scanner.CellNet) THEN
  2238. SetNextInComment(recentComment,module);
  2239. module.SetClosingComment(recentComment);
  2240. recentComment := NIL;
  2241. END;
  2242. *)
  2243. END;
  2244. END;
  2245. IF conditionalCount # 0 THEN Error (token.position, Basic.InvalidCode, "missing conditional end") END;
  2246. IF Trace THEN E( "Module" ) END;
  2247. RETURN module
  2248. END Module;
  2249. (** check if another module declaration is available after recent module parsing -> for parsing and compiling multiple modules within a single file **)
  2250. PROCEDURE NextModule*(): BOOLEAN;
  2251. BEGIN
  2252. RETURN Peek(Scanner.Module) OR Peek(Scanner.CellNet);
  2253. END NextModule;
  2254. END Parser;
  2255. (* utilities *)
  2256. PROCEDURE AppendModifier(VAR list: SyntaxTree.Modifier; modifier: SyntaxTree.Modifier);
  2257. VAR this, next: SyntaxTree.Modifier;
  2258. BEGIN
  2259. IF list = NIL THEN list := modifier
  2260. ELSE
  2261. this := list;
  2262. next := list.nextModifier;
  2263. WHILE next # NIL DO
  2264. this := next;
  2265. next := this.nextModifier;
  2266. END;
  2267. this.SetNext(modifier);
  2268. END;
  2269. END AppendModifier;
  2270. (** parser retrieval **)
  2271. PROCEDURE NewParser*( scanner: Scanner.Scanner; diagnostics: Diagnostics.Diagnostics; CONST definitions: ARRAY OF CHAR): Parser;
  2272. VAR parser: Parser;
  2273. BEGIN
  2274. NEW( parser, scanner, diagnostics, definitions ); RETURN parser;
  2275. END NewParser;
  2276. END FoxParser.
  2277. System.FreeDownTo FoxParser ~