| 1 | lexer grammar FortranLexer;
|
|---|
| 2 |
|
|---|
| 3 | options {
|
|---|
| 4 | tokenVocab=FortranLexer;
|
|---|
| 5 | }
|
|---|
| 6 |
|
|---|
| 7 | @header {
|
|---|
| 8 | /**
|
|---|
| 9 | * Copyright (c) 2005, 2006 Los Alamos National Security, LLC. This
|
|---|
| 10 | * material was produced under U.S. Government contract DE-
|
|---|
| 11 | * AC52-06NA25396 for Los Alamos National Laboratory (LANL), which is
|
|---|
| 12 | * operated by the Los Alamos National Security, LLC (LANS) for the
|
|---|
| 13 | * U.S. Department of Energy. The U.S. Government has rights to use,
|
|---|
| 14 | * reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR
|
|---|
| 15 | * LANS MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY
|
|---|
| 16 | * LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to
|
|---|
| 17 | * produce derivative works, such modified software should be clearly
|
|---|
| 18 | * marked, so as not to confuse it with the version available from
|
|---|
| 19 | * LANL.
|
|---|
| 20 | *
|
|---|
| 21 | * Additionally, this program and the accompanying materials are made
|
|---|
| 22 | * available under the terms of the Eclipse Public License v1.0 which
|
|---|
| 23 | * accompanies this distribution, and is available at
|
|---|
| 24 | * http://www.eclipse.org/legal/epl-v10.html
|
|---|
| 25 | */
|
|---|
| 26 |
|
|---|
| 27 | /**
|
|---|
| 28 | *
|
|---|
| 29 | * @author Craig E Rasmussen, Christopher D. Rickett, Jeffrey Overbey
|
|---|
| 30 | */
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 | package dev.civl.abc.front.fortran.old.preproc;
|
|---|
| 34 |
|
|---|
| 35 | import java.io.File;
|
|---|
| 36 | import java.io.IOException;
|
|---|
| 37 | import java.util.ArrayList;
|
|---|
| 38 | import java.util.Stack;
|
|---|
| 39 | import java.util.TreeSet;
|
|---|
| 40 |
|
|---|
| 41 | import dev.civl.abc.token.IF.CivlcToken;
|
|---|
| 42 | import dev.civl.abc.token.IF.CivlcToken.TokenVocabulary;
|
|---|
| 43 | import dev.civl.abc.token.IF.Formation;
|
|---|
| 44 | import dev.civl.abc.token.IF.SourceFile;
|
|---|
| 45 | import dev.civl.abc.token.IF.TokenFactory;
|
|---|
| 46 | import dev.civl.abc.token.IF.Tokens;
|
|---|
| 47 | }
|
|---|
| 48 |
|
|---|
| 49 | @members {
|
|---|
| 50 | //Fields:
|
|---|
| 51 | private Token prevToken;
|
|---|
| 52 | private int sourceForm;
|
|---|
| 53 | private boolean continueFlag;
|
|---|
| 54 | private boolean includeLine;
|
|---|
| 55 | private boolean inFormat;
|
|---|
| 56 | private ArrayList<String> includeDirs;
|
|---|
| 57 | private Stack<FortranStream> oldStreams;
|
|---|
| 58 |
|
|---|
| 59 | //OFP_ABC
|
|---|
| 60 | private Stack<Integer> oldFileIndexes;
|
|---|
| 61 | private int fileCounter = 0;
|
|---|
| 62 | private Integer fileIndex = Integer.valueOf(fileCounter);
|
|---|
| 63 | private TokenFactory tokenFactory = Tokens.newTokenFactory();
|
|---|
| 64 | private Formation inclusionFormation;
|
|---|
| 65 | //OFP_ABC
|
|---|
| 66 |
|
|---|
| 67 | protected StringBuilder whiteText = new StringBuilder();
|
|---|
| 68 |
|
|---|
| 69 | //Methods:
|
|---|
| 70 | public Token emit() {
|
|---|
| 71 | int start = state.tokenStartCharIndex;
|
|---|
| 72 | int stop = getCharIndex() - 1;
|
|---|
| 73 | // TODO - this is a start at fixing the line:column information in tokens inserted
|
|---|
| 74 | // by the lexer. In future the stop should at least be the length of token text.
|
|---|
| 75 | if (stop < 0) {
|
|---|
| 76 | stop = start; // for now
|
|---|
| 77 | }
|
|---|
| 78 | this.inclusionFormation = tokenFactory.newInclusion(new SourceFile(new File(this.input.getSourceName()), this.fileIndex.intValue()));
|
|---|
| 79 | CivlcToken t = tokenFactory.newCivlcToken(input, state.type, state.channel, start, stop, inclusionFormation, this.input.getLine(), this.input.getCharPositionInLine(), TokenVocabulary.FORTRAN);
|
|---|
| 80 | t.setLine(state.tokenStartLine);
|
|---|
| 81 | t.setText(state.text);
|
|---|
| 82 | t.setCharPositionInLine(state.tokenStartCharPositionInLine);
|
|---|
| 83 |
|
|---|
| 84 | if (state.channel == HIDDEN) {
|
|---|
| 85 | whiteText.append(getText());
|
|---|
| 86 | } else {
|
|---|
| 87 | t.setWhiteText(whiteText.toString());
|
|---|
| 88 | whiteText.delete(0, whiteText.length());
|
|---|
| 89 | }
|
|---|
| 90 |
|
|---|
| 91 | emit(t);
|
|---|
| 92 | return t;
|
|---|
| 93 | }
|
|---|
| 94 |
|
|---|
| 95 | public boolean isKeyword(Token tk) {
|
|---|
| 96 | return isKeyword(tk.getType());
|
|---|
| 97 | } // end isKeyword()
|
|---|
| 98 |
|
|---|
| 99 | public boolean isKeyword(int tokenType) {
|
|---|
| 100 | switch (tokenType) {
|
|---|
| 101 | case T_BEGIN_KEYWORDS:
|
|---|
| 102 | case T_INTEGER:
|
|---|
| 103 | case T_REAL:
|
|---|
| 104 | case T_COMPLEX:
|
|---|
| 105 | case T_CHARACTER:
|
|---|
| 106 | case T_LOGICAL:
|
|---|
| 107 | case T_ABSTRACT:
|
|---|
| 108 | case T_ACQUIRED_LOCK:
|
|---|
| 109 | case T_ALL:
|
|---|
| 110 | case T_ALLOCATABLE:
|
|---|
| 111 | case T_ALLOCATE:
|
|---|
| 112 | case T_ASSIGNMENT:
|
|---|
| 113 | case T_ASSIGN:
|
|---|
| 114 | case T_ASSOCIATE:
|
|---|
| 115 | case T_ASYNCHRONOUS:
|
|---|
| 116 | case T_BACKSPACE:
|
|---|
| 117 | case T_BLOCK:
|
|---|
| 118 | case T_BLOCKDATA:
|
|---|
| 119 | case T_CALL:
|
|---|
| 120 | case T_CASE:
|
|---|
| 121 | case T_CLASS:
|
|---|
| 122 | case T_CLOSE:
|
|---|
| 123 | case T_CODIMENSION:
|
|---|
| 124 | case T_COMMON:
|
|---|
| 125 | case T_CONCURRENT:
|
|---|
| 126 | case T_CONTAINS:
|
|---|
| 127 | case T_CONTIGUOUS:
|
|---|
| 128 | case T_CONTINUE:
|
|---|
| 129 | case T_CRITICAL:
|
|---|
| 130 | case T_CYCLE:
|
|---|
| 131 | case T_DATA:
|
|---|
| 132 | case T_DEFAULT:
|
|---|
| 133 | case T_DEALLOCATE:
|
|---|
| 134 | case T_DEFERRED:
|
|---|
| 135 | case T_DO:
|
|---|
| 136 | case T_DOUBLE:
|
|---|
| 137 | case T_DOUBLEPRECISION:
|
|---|
| 138 | case T_DOUBLECOMPLEX:
|
|---|
| 139 | case T_ELEMENTAL:
|
|---|
| 140 | case T_ELSE:
|
|---|
| 141 | case T_ELSEIF:
|
|---|
| 142 | case T_ELSEWHERE:
|
|---|
| 143 | case T_ENTRY:
|
|---|
| 144 | case T_ENUM:
|
|---|
| 145 | case T_ENUMERATOR:
|
|---|
| 146 | case T_ERROR:
|
|---|
| 147 | case T_EQUIVALENCE:
|
|---|
| 148 | case T_EXIT:
|
|---|
| 149 | case T_EXTENDS:
|
|---|
| 150 | case T_EXTERNAL:
|
|---|
| 151 | case T_FILE:
|
|---|
| 152 | case T_FINAL:
|
|---|
| 153 | case T_FLUSH:
|
|---|
| 154 | case T_FORALL:
|
|---|
| 155 | case T_FORMAT:
|
|---|
| 156 | case T_FORMATTED:
|
|---|
| 157 | case T_FUNCTION:
|
|---|
| 158 | case T_GENERIC:
|
|---|
| 159 | case T_GO:
|
|---|
| 160 | case T_GOTO:
|
|---|
| 161 | case T_IF:
|
|---|
| 162 | case T_IMAGES:
|
|---|
| 163 | case T_IMPLICIT:
|
|---|
| 164 | case T_IMPORT:
|
|---|
| 165 | case T_IN:
|
|---|
| 166 | case T_INOUT:
|
|---|
| 167 | case T_INTENT:
|
|---|
| 168 | case T_INTERFACE:
|
|---|
| 169 | case T_INTRINSIC:
|
|---|
| 170 | case T_INQUIRE:
|
|---|
| 171 | case T_LOCK:
|
|---|
| 172 | case T_MEMORY:
|
|---|
| 173 | case T_MODULE:
|
|---|
| 174 | case T_NAMELIST:
|
|---|
| 175 | case T_NONE:
|
|---|
| 176 | case T_NON_INTRINSIC:
|
|---|
| 177 | case T_NON_OVERRIDABLE:
|
|---|
| 178 | case T_NOPASS:
|
|---|
| 179 | case T_NULLIFY:
|
|---|
| 180 | case T_ONLY:
|
|---|
| 181 | case T_OPEN:
|
|---|
| 182 | case T_OPERATOR:
|
|---|
| 183 | case T_OPTIONAL:
|
|---|
| 184 | case T_OUT:
|
|---|
| 185 | case T_PARAMETER:
|
|---|
| 186 | case T_PASS:
|
|---|
| 187 | case T_PAUSE:
|
|---|
| 188 | case T_POINTER:
|
|---|
| 189 | case T_PRINT:
|
|---|
| 190 | case T_PRECISION:
|
|---|
| 191 | case T_PRIVATE:
|
|---|
| 192 | case T_PROCEDURE:
|
|---|
| 193 | case T_PROGRAM:
|
|---|
| 194 | case T_PROTECTED:
|
|---|
| 195 | case T_PUBLIC:
|
|---|
| 196 | case T_PURE:
|
|---|
| 197 | case T_READ:
|
|---|
| 198 | case T_RECURSIVE:
|
|---|
| 199 | case T_RESULT:
|
|---|
| 200 | case T_RETURN:
|
|---|
| 201 | case T_REWIND:
|
|---|
| 202 | case T_SAVE:
|
|---|
| 203 | case T_SELECT:
|
|---|
| 204 | case T_SELECTCASE:
|
|---|
| 205 | case T_SELECTTYPE:
|
|---|
| 206 | case T_SEQUENCE:
|
|---|
| 207 | case T_STOP:
|
|---|
| 208 | case T_SUBMODULE:
|
|---|
| 209 | case T_SUBROUTINE:
|
|---|
| 210 | case T_SYNC:
|
|---|
| 211 | case T_TARGET:
|
|---|
| 212 | case T_THEN:
|
|---|
| 213 | case T_TO:
|
|---|
| 214 | case T_TYPE:
|
|---|
| 215 | case T_UNFORMATTED:
|
|---|
| 216 | case T_UNLOCK:
|
|---|
| 217 | case T_USE:
|
|---|
| 218 | case T_VALUE:
|
|---|
| 219 | case T_VOLATILE:
|
|---|
| 220 | case T_WAIT:
|
|---|
| 221 | case T_WHERE:
|
|---|
| 222 | case T_WHILE:
|
|---|
| 223 | case T_WRITE:
|
|---|
| 224 | case T_WITHTEAM:
|
|---|
| 225 | case T_WITH:
|
|---|
| 226 | case T_TEAM:
|
|---|
| 227 | case T_TOPOLOGY:
|
|---|
| 228 | case T_EVENT:
|
|---|
| 229 | case T_LOCKSET:
|
|---|
| 230 | case T_FINISH:
|
|---|
| 231 | case T_SPAWN:
|
|---|
| 232 | case T_COPOINTER:
|
|---|
| 233 | case T_COTARGET:
|
|---|
| 234 | case T_ENDASSOCIATE:
|
|---|
| 235 | case T_ENDBLOCK:
|
|---|
| 236 | case T_ENDBLOCKDATA:
|
|---|
| 237 | case T_ENDCRITICAL:
|
|---|
| 238 | case T_ENDDO:
|
|---|
| 239 | case T_ENDENUM:
|
|---|
| 240 | case T_ENDFILE:
|
|---|
| 241 | case T_ENDFORALL:
|
|---|
| 242 | case T_ENDFUNCTION:
|
|---|
| 243 | case T_ENDIF:
|
|---|
| 244 | case T_ENDMODULE:
|
|---|
| 245 | case T_ENDINTERFACE:
|
|---|
| 246 | case T_ENDPROCEDURE:
|
|---|
| 247 | case T_ENDPROGRAM:
|
|---|
| 248 | case T_ENDSELECT:
|
|---|
| 249 | case T_ENDSUBMODULE:
|
|---|
| 250 | case T_ENDSUBROUTINE:
|
|---|
| 251 | case T_ENDTYPE:
|
|---|
| 252 | case T_ENDWHERE:
|
|---|
| 253 | case T_END:
|
|---|
| 254 | case T_DIMENSION:
|
|---|
| 255 | case T_KIND:
|
|---|
| 256 | case T_LEN:
|
|---|
| 257 | case T_BIND:
|
|---|
| 258 | case T_END_KEYWORDS:
|
|---|
| 259 | case T_PRAGMA:
|
|---|
| 260 | return true;
|
|---|
| 261 | default:
|
|---|
| 262 | return false;
|
|---|
| 263 | }
|
|---|
| 264 | // (by Manchun) Commenting out the original tricky implementation because it requires
|
|---|
| 265 | // ANTLR to always generates the constants for tokens in the same order
|
|---|
| 266 | // as they were in the lexer file.
|
|---|
| 267 | // however, this is apparently not true for antlr-3.5, which generates
|
|---|
| 268 | // constants by alphabetic order of the token names.
|
|---|
| 269 | // if (tokenType > T_BEGIN_KEYWORDS && tokenType < T_END_KEYWORDS) {
|
|---|
| 270 | // return true;
|
|---|
| 271 | // } else {
|
|---|
| 272 | // return false;
|
|---|
| 273 | // }
|
|---|
| 274 | } // end isKeyword()
|
|---|
| 275 |
|
|---|
| 276 |
|
|---|
| 277 |
|
|---|
| 278 | /**
|
|---|
| 279 | * This is necessary because the lexer class caches some values from the
|
|---|
| 280 | * input stream. Here we reset them to what the current input stream values
|
|---|
| 281 | * are. This is done when we switch streams for including files.
|
|---|
| 282 | */
|
|---|
| 283 | private void resetLexerState() {
|
|---|
| 284 | state.tokenStartCharIndex = input.index();
|
|---|
| 285 | state.tokenStartCharPositionInLine = input.getCharPositionInLine();
|
|---|
| 286 | state.tokenStartLine = input.getLine();
|
|---|
| 287 | state.token = null;
|
|---|
| 288 | state.text = null;
|
|---|
| 289 | }// end resetLexerState()
|
|---|
| 290 |
|
|---|
| 291 | // overrides nextToken in superclass
|
|---|
| 292 | public Token nextToken() {
|
|---|
| 293 | CivlcToken tk = tokenFactory.newCivlcToken(super.nextToken(),
|
|---|
| 294 | inclusionFormation, TokenVocabulary.FORTRAN);
|
|---|
| 295 |
|
|---|
| 296 | if (tk.getType() == EOF) {
|
|---|
| 297 | CivlcToken eofToken;
|
|---|
| 298 | FortranStream fs = getInput();
|
|---|
| 299 |
|
|---|
| 300 | tk.setChannel(Token.DEFAULT_CHANNEL);
|
|---|
| 301 | this.inclusionFormation = tokenFactory.newInclusion(new SourceFile(
|
|---|
| 302 | new File(this.input.getSourceName()), this.fileIndex
|
|---|
| 303 | .intValue()));
|
|---|
| 304 | eofToken = tokenFactory.newCivlcToken(this.input, T_EOF,
|
|---|
| 305 | Token.DEFAULT_CHANNEL, this.input.index(),
|
|---|
| 306 | this.input.index() + 1, inclusionFormation, this.input.getLine(), this.input.getCharPositionInLine(), TokenVocabulary.FORTRAN);
|
|---|
| 307 |
|
|---|
| 308 | if (this.oldStreams != null && this.oldStreams.empty() == false) {
|
|---|
| 309 |
|
|---|
| 310 | // TODO - provide better information about the location of this
|
|---|
| 311 | // token
|
|---|
| 312 | // It is probably ok for it to start at last character position
|
|---|
| 313 | // in file but
|
|---|
| 314 | // consider the end position of the token.
|
|---|
| 315 | eofToken.setLine(state.tokenStartLine);
|
|---|
| 316 | eofToken.setCharPositionInLine(state.tokenStartCharPositionInLine);
|
|---|
| 317 |
|
|---|
| 318 | eofToken.setText(fs.getFileName() + ":" + fs.getAbsolutePath());
|
|---|
| 319 |
|
|---|
| 320 | tk = eofToken;
|
|---|
| 321 | /*
|
|---|
| 322 | * We have at least one previous input stream on the stack,
|
|---|
| 323 | * meaning we should be at the end of an included file. Switch
|
|---|
| 324 | * back to the previous stream and continue.
|
|---|
| 325 | */
|
|---|
| 326 | this.input = this.oldStreams.pop();
|
|---|
| 327 | this.fileIndex = this.oldFileIndexes.pop();
|
|---|
| 328 | /* Is this ok to do?? */
|
|---|
| 329 | resetLexerState();
|
|---|
| 330 | } else {
|
|---|
| 331 | tk.setText(fs.getFileName() + ":" + fs.getAbsolutePath());
|
|---|
| 332 | eofToken = tk;
|
|---|
| 333 | }
|
|---|
| 334 |
|
|---|
| 335 | return tk;
|
|---|
| 336 | }
|
|---|
| 337 |
|
|---|
| 338 | if (tk.getType() != LINE_COMMENT && tk.getType() != WS
|
|---|
| 339 | && tk.getType() != PREPROCESS_LINE) {
|
|---|
| 340 | prevToken = tk;
|
|---|
| 341 | }
|
|---|
| 342 |
|
|---|
| 343 | if (tk.getType() == T_EOS && continueFlag == true) {
|
|---|
| 344 | tk.setChannel(99);
|
|---|
| 345 | } else if (continueFlag == true) {
|
|---|
| 346 | if (tk.getType() != LINE_COMMENT && tk.getType() != WS
|
|---|
| 347 | && tk.getType() != PREPROCESS_LINE
|
|---|
| 348 | && tk.getType() != CONTINUE_CHAR) {
|
|---|
| 349 | // if the token we have is not T_EOS or any kind of WS or
|
|---|
| 350 | // comment, and we have a continue, then this should be the
|
|---|
| 351 | // first token on the line folliwng the '&'. this means that
|
|---|
| 352 | // we only have one '&' (no '&' on the second line) and we
|
|---|
| 353 | // need to clear the flag so we know to process the T_EOS.
|
|---|
| 354 | continueFlag = false;
|
|---|
| 355 | }
|
|---|
| 356 | }
|
|---|
| 357 |
|
|---|
| 358 | return tk;
|
|---|
| 359 | } // end nextToken()
|
|---|
| 360 |
|
|---|
| 361 | public int getIgnoreChannelNumber() {
|
|---|
| 362 | // return the channel number that antlr uses for ignoring a token
|
|---|
| 363 | return 99;
|
|---|
| 364 | }// end getIgnoreChannelNumber()
|
|---|
| 365 |
|
|---|
| 366 | public FortranStream getInput() {
|
|---|
| 367 | return (FortranStream) this.input;
|
|---|
| 368 | }
|
|---|
| 369 |
|
|---|
| 370 | public Formation getFormation() {
|
|---|
| 371 | assert this.inclusionFormation != null;
|
|---|
| 372 | return this.inclusionFormation;
|
|---|
| 373 | }
|
|---|
| 374 |
|
|---|
| 375 | /**
|
|---|
| 376 | * Do this here because not sure how to get antlr to generate the init code.
|
|---|
| 377 | * It doesn't seem to do anything with the @init block below. This is called
|
|---|
| 378 | * by FortranMain().
|
|---|
| 379 | */
|
|---|
| 380 | public FortranLexer(FortranStream input) {
|
|---|
| 381 | super(input);
|
|---|
| 382 | this.sourceForm = input.getSourceForm();
|
|---|
| 383 | this.prevToken = null;
|
|---|
| 384 | this.continueFlag = false;
|
|---|
| 385 | this.includeLine = false;
|
|---|
| 386 | this.inFormat = false;
|
|---|
| 387 | this.oldStreams = new Stack<FortranStream>();
|
|---|
| 388 | this.oldFileIndexes = new Stack<Integer>();
|
|---|
| 389 | // TODO: idx
|
|---|
| 390 | this.includeDirs = new ArrayList<String>();
|
|---|
| 391 | this.inclusionFormation = tokenFactory
|
|---|
| 392 | .newInclusion(new SourceFile(new File(this.input
|
|---|
| 393 | .getSourceName()), this.fileIndex.intValue()));
|
|---|
| 394 | } // end constructor()
|
|---|
| 395 |
|
|---|
| 396 | public void setIncludeDirs(File[] systemIncludePaths, File[] userIncludePaths, File[] sourceUnit) {
|
|---|
| 397 | TreeSet<String> pathSet = new TreeSet<String>();
|
|---|
| 398 |
|
|---|
| 399 | if (systemIncludePaths != null)
|
|---|
| 400 | for (File f : systemIncludePaths) {
|
|---|
| 401 | if (f != null && f.getParentFile() != null)
|
|---|
| 402 | pathSet.add(f.getParentFile().getAbsolutePath());
|
|---|
| 403 | }
|
|---|
| 404 | if (userIncludePaths != null)
|
|---|
| 405 | for (File f : userIncludePaths) {
|
|---|
| 406 | if (f != null && f.getParentFile() != null)
|
|---|
| 407 | pathSet.add(f.getParentFile().getAbsolutePath());
|
|---|
| 408 | }
|
|---|
| 409 | if (sourceUnit != null)
|
|---|
| 410 | for (File f : sourceUnit) {
|
|---|
| 411 | if (f != null && f.getParentFile() != null)
|
|---|
| 412 | pathSet.add(f.getParentFile().getAbsolutePath());
|
|---|
| 413 | }
|
|---|
| 414 | for (String s : pathSet) {
|
|---|
| 415 | includeDirs.add(s);
|
|---|
| 416 | }
|
|---|
| 417 |
|
|---|
| 418 | }// end setIncludeDirs()
|
|---|
| 419 |
|
|---|
| 420 | private File findFile(String fileName) {
|
|---|
| 421 | File tmpFile;
|
|---|
| 422 | String tmpPath;
|
|---|
| 423 | StringBuffer newFileName;
|
|---|
| 424 |
|
|---|
| 425 | tmpFile = new File(fileName);
|
|---|
| 426 | if (tmpFile.exists() == false) {
|
|---|
| 427 | /*
|
|---|
| 428 | * the file doesn't exist by the given name from the include line,
|
|---|
| 429 | * so we need to append it to each include dir and search.
|
|---|
| 430 | */
|
|---|
| 431 | for (int i = 0; i < this.includeDirs.size(); i++) {
|
|---|
| 432 | tmpPath = this.includeDirs.get(i);
|
|---|
| 433 |
|
|---|
| 434 | newFileName = new StringBuffer();
|
|---|
| 435 |
|
|---|
| 436 | /*
|
|---|
| 437 | * Build the new file name with the path. Add separator to end
|
|---|
| 438 | * of path if necessary (unix specific).
|
|---|
| 439 | */
|
|---|
| 440 | newFileName = newFileName.append(tmpPath);
|
|---|
| 441 | if (tmpPath.charAt(tmpPath.length() - 1) != '/') {
|
|---|
| 442 | newFileName = newFileName.append('/');
|
|---|
| 443 | }
|
|---|
| 444 | newFileName = newFileName.append(fileName);
|
|---|
| 445 |
|
|---|
| 446 | /* Try opening the new file. */
|
|---|
| 447 | tmpFile = new File(newFileName.toString());
|
|---|
| 448 | if (tmpFile.exists() == true) {
|
|---|
| 449 | return tmpFile;
|
|---|
| 450 | }
|
|---|
| 451 | }
|
|---|
| 452 |
|
|---|
| 453 | /* File did not exist. */
|
|---|
| 454 | return null;
|
|---|
| 455 | } else {
|
|---|
| 456 | return tmpFile;
|
|---|
| 457 | }
|
|---|
| 458 | } // end findFile()
|
|---|
| 459 |
|
|---|
| 460 | private String includeFile() {
|
|---|
| 461 | String filename = "ERROR: no file name";
|
|---|
| 462 | File includedFile = null;
|
|---|
| 463 |
|
|---|
| 464 | if (prevToken != null) {
|
|---|
| 465 | String charConst = null;
|
|---|
| 466 | FortranStream includedStream = null;
|
|---|
| 467 |
|
|---|
| 468 | charConst = prevToken.getText();
|
|---|
| 469 | filename = charConst.substring(1, charConst.length() - 1);
|
|---|
| 470 |
|
|---|
| 471 | /* Find the file, including it's complete path. */
|
|---|
| 472 | includedFile = findFile(filename);
|
|---|
| 473 | if (includedFile == null) {
|
|---|
| 474 | System.err.println("WARNING: Could not find file '" + filename
|
|---|
| 475 | + "'");
|
|---|
| 476 | return filename + ":ERROR_FILE_NOT_FOUND";
|
|---|
| 477 | }
|
|---|
| 478 |
|
|---|
| 479 | /* Create a new stream for the included file. */
|
|---|
| 480 | try {
|
|---|
| 481 | // the included file should have the save source form as
|
|---|
| 482 | // original
|
|---|
| 483 | includedStream = new FortranStream(filename,
|
|---|
| 484 | includedFile.getAbsolutePath(), this.sourceForm);
|
|---|
| 485 | } catch (IOException e) {
|
|---|
| 486 | System.err.println("WARNING: Could not open file '" + filename
|
|---|
| 487 | + "'");
|
|---|
| 488 | e.printStackTrace();
|
|---|
| 489 | return includedFile.getAbsolutePath();
|
|---|
| 490 | }
|
|---|
| 491 |
|
|---|
| 492 | /* Save current character stream. */
|
|---|
| 493 | oldStreams.push(getInput());
|
|---|
| 494 | oldFileIndexes.push(fileIndex);
|
|---|
| 495 | this.fileCounter++;
|
|---|
| 496 | this.fileIndex = Integer.valueOf(this.fileCounter);
|
|---|
| 497 | this.input = includedStream;
|
|---|
| 498 | /* Is this ok to do?? */
|
|---|
| 499 | resetLexerState();
|
|---|
| 500 | } else {
|
|---|
| 501 | System.err.println("ERROR: Unable to determine file name from "
|
|---|
| 502 | + "include line");
|
|---|
| 503 | }
|
|---|
| 504 |
|
|---|
| 505 | return filename + ":" + includedFile.getAbsolutePath();
|
|---|
| 506 |
|
|---|
| 507 | } // end includeFile()
|
|---|
| 508 |
|
|---|
| 509 | }
|
|---|
| 510 |
|
|---|
| 511 | @init {
|
|---|
| 512 | prevToken = null;
|
|---|
| 513 | }
|
|---|
| 514 |
|
|---|
| 515 | /*
|
|---|
| 516 | * Lexer rules
|
|---|
| 517 | */
|
|---|
| 518 |
|
|---|
| 519 | /*
|
|---|
| 520 | * Note: antlr sometimes has LL(*) failures with the grammars, but not always.
|
|---|
| 521 | * it seems that it may be the timeout issue that was mentioned..
|
|---|
| 522 | */
|
|---|
| 523 |
|
|---|
| 524 | // Support for language extension points
|
|---|
| 525 | T_NO_LANGUAGE_EXTENSION : {false}? 'no extension' ; // can't be recognized
|
|---|
| 526 |
|
|---|
| 527 |
|
|---|
| 528 | T_EOS
|
|---|
| 529 | @after {
|
|---|
| 530 | // Throw away T_EOS if at beginning of file or after an include,
|
|---|
| 531 | // T_EOS processing by the parser only works after the first statement so
|
|---|
| 532 | // any blank lines before statements in a file must be hidden.
|
|---|
| 533 | if (prevToken == null) {
|
|---|
| 534 | state.channel = HIDDEN;
|
|---|
| 535 | } else if (prevToken.getType() == T_EOS || prevToken.getType() == T_INCLUDE_NAME) {
|
|---|
| 536 | state.channel = HIDDEN;
|
|---|
| 537 | }
|
|---|
| 538 |
|
|---|
| 539 | if (includeLine) {
|
|---|
| 540 | // Part of include file handling.
|
|---|
| 541 | state.text = includeFile();
|
|---|
| 542 | state.type = T_INCLUDE_NAME;
|
|---|
| 543 | includeLine = false;
|
|---|
| 544 | }
|
|---|
| 545 |
|
|---|
| 546 | // Make sure we clear the flag saying we're in a format-stmt
|
|---|
| 547 | inFormat = false;
|
|---|
| 548 | }
|
|---|
| 549 | : ';'
|
|---|
| 550 | | ('\r')? ('\n')
|
|---|
| 551 | ;
|
|---|
| 552 |
|
|---|
| 553 |
|
|---|
| 554 | /* if this is a fragment, the generated code never seems to execute the
|
|---|
| 555 | * action. the action needs to set the flag so T_EOS knows whether it should
|
|---|
| 556 | * be channel 99'ed or not (ignore T_EOS if continuation is true, which is the
|
|---|
| 557 | * case of the & at the end of a line).
|
|---|
| 558 | */
|
|---|
| 559 | CONTINUE_CHAR : '&' {
|
|---|
| 560 | continueFlag = !continueFlag;
|
|---|
| 561 | $channel = HIDDEN;
|
|---|
| 562 | }
|
|---|
| 563 | ;
|
|---|
| 564 |
|
|---|
| 565 |
|
|---|
| 566 | // R427 from char-literal-constant
|
|---|
| 567 | T_CHAR_CONSTANT
|
|---|
| 568 | : ('\'' ( SQ_Rep_Char )* '\'')+ {
|
|---|
| 569 | if (includeLine)
|
|---|
| 570 | $channel = HIDDEN;
|
|---|
| 571 | }
|
|---|
| 572 | | ('\"' ( DQ_Rep_Char )* '\"')+ {
|
|---|
| 573 | if (includeLine)
|
|---|
| 574 | $channel = HIDDEN;
|
|---|
| 575 | }
|
|---|
| 576 | ;
|
|---|
| 577 |
|
|---|
| 578 | T_DIGIT_STRING
|
|---|
| 579 | : Digit_String
|
|---|
| 580 | ;
|
|---|
| 581 |
|
|---|
| 582 | // R412
|
|---|
| 583 | BINARY_CONSTANT
|
|---|
| 584 | : ('b'|'B') '\'' ('0'..'1')+ '\''
|
|---|
| 585 | | ('b'|'B') '\"' ('0'..'1')+ '\"'
|
|---|
| 586 | ;
|
|---|
| 587 |
|
|---|
| 588 | // R413
|
|---|
| 589 | OCTAL_CONSTANT
|
|---|
| 590 | : ('o'|'O') '\'' ('0'..'7')+ '\''
|
|---|
| 591 | | ('o'|'O') '\"' ('0'..'7')+ '\"'
|
|---|
| 592 | ;
|
|---|
| 593 |
|
|---|
| 594 | // R414
|
|---|
| 595 | HEX_CONSTANT
|
|---|
| 596 | : ('z'|'Z') '\'' (Digit|'a'..'f'|'A'..'F')+ '\''
|
|---|
| 597 | | ('z'|'Z') '\"' (Digit|'a'..'f'|'A'..'F')+ '\"'
|
|---|
| 598 | ;
|
|---|
| 599 |
|
|---|
| 600 |
|
|---|
| 601 | WS : (' '|'\r'|'\t'|'\u000C') {
|
|---|
| 602 | $channel = HIDDEN;
|
|---|
| 603 | }
|
|---|
| 604 | ;
|
|---|
| 605 |
|
|---|
| 606 | /*
|
|---|
| 607 | * fragments
|
|---|
| 608 | */
|
|---|
| 609 |
|
|---|
| 610 | // R409 digit_string
|
|---|
| 611 | fragment
|
|---|
| 612 | Digit_String : Digit+ ;
|
|---|
| 613 |
|
|---|
| 614 |
|
|---|
| 615 | // R302 alphanumeric_character
|
|---|
| 616 | fragment
|
|---|
| 617 | Alphanumeric_Character : Letter | Digit | '_' ;
|
|---|
| 618 |
|
|---|
| 619 | fragment
|
|---|
| 620 | Special_Character
|
|---|
| 621 | : ' ' .. '/'
|
|---|
| 622 | | ':' .. '@'
|
|---|
| 623 | | '[' .. '^'
|
|---|
| 624 | | '`'
|
|---|
| 625 | | '{' .. '~'
|
|---|
| 626 | ;
|
|---|
| 627 |
|
|---|
| 628 | fragment
|
|---|
| 629 | Rep_Char : ~('\'' | '\"') ;
|
|---|
| 630 |
|
|---|
| 631 | fragment
|
|---|
| 632 | SQ_Rep_Char : ~('\'') ;
|
|---|
| 633 | fragment
|
|---|
| 634 | DQ_Rep_Char : ~('\"') ;
|
|---|
| 635 |
|
|---|
| 636 | fragment
|
|---|
| 637 | Letter : ('a'..'z' | 'A'..'Z') ;
|
|---|
| 638 |
|
|---|
| 639 | fragment
|
|---|
| 640 | Digit : '0'..'9' ;
|
|---|
| 641 |
|
|---|
| 642 | PREPROCESS_LINE : '#' ~('\n'|'\r')* {
|
|---|
| 643 | $channel = HIDDEN;
|
|---|
| 644 | } ;
|
|---|
| 645 |
|
|---|
| 646 | T_INCLUDE
|
|---|
| 647 | options {k=1;} : 'INCLUDE' {
|
|---|
| 648 | includeLine = true;
|
|---|
| 649 | };
|
|---|
| 650 |
|
|---|
| 651 |
|
|---|
| 652 | /*
|
|---|
| 653 | * from fortran03_lexer.g
|
|---|
| 654 | */
|
|---|
| 655 |
|
|---|
| 656 | T_ASTERISK : '*' ;
|
|---|
| 657 | T_COLON : ':' ;
|
|---|
| 658 | T_COLON_COLON : '::' ;
|
|---|
| 659 | T_COMMA : ',' ;
|
|---|
| 660 | T_EQUALS : '=' ;
|
|---|
| 661 | T_EQ_EQ : '==' ;
|
|---|
| 662 | T_EQ_GT : '=>' ;
|
|---|
| 663 | T_GREATERTHAN : '>' ;
|
|---|
| 664 | T_GREATERTHAN_EQ: '>=' ;
|
|---|
| 665 | T_LESSTHAN : '<' ;
|
|---|
| 666 | T_LESSTHAN_EQ : '<=' ;
|
|---|
| 667 | T_LBRACKET : '[' ;
|
|---|
| 668 | T_LPAREN : '(' ;
|
|---|
| 669 | T_MINUS : '-' ;
|
|---|
| 670 | T_PERCENT : '%' ;
|
|---|
| 671 | T_PLUS : '+' ;
|
|---|
| 672 | T_POWER : '**' ;
|
|---|
| 673 | T_SLASH : '/' ;
|
|---|
| 674 | T_SLASH_EQ : '/=' ;
|
|---|
| 675 | T_SLASH_SLASH : '//' ;
|
|---|
| 676 | T_RBRACKET : ']' ;
|
|---|
| 677 | T_RPAREN : ')' ;
|
|---|
| 678 | T_UNDERSCORE : '_' ;
|
|---|
| 679 |
|
|---|
| 680 | // begin Rice additions --------------------------
|
|---|
| 681 | T_AT : '@' ;
|
|---|
| 682 | // end Rice additions ----------------------------
|
|---|
| 683 |
|
|---|
| 684 | T_EQ : '.EQ.' ;
|
|---|
| 685 | T_NE : '.NE.' ;
|
|---|
| 686 | T_LT : '.LT.' ;
|
|---|
| 687 | T_LE : '.LE.' ;
|
|---|
| 688 | T_GT : '.GT.' ;
|
|---|
| 689 | T_GE : '.GE.' ;
|
|---|
| 690 |
|
|---|
| 691 | T_TRUE : '.TRUE.' ;
|
|---|
| 692 | T_FALSE : '.FALSE.' ;
|
|---|
| 693 |
|
|---|
| 694 | T_NOT : '.NOT.' ;
|
|---|
| 695 | T_AND : '.AND.' ;
|
|---|
| 696 | T_OR : '.OR.' ;
|
|---|
| 697 | T_EQV : '.EQV.' ;
|
|---|
| 698 | T_NEQV : '.NEQV.';
|
|---|
| 699 |
|
|---|
| 700 | T_PERIOD_EXPONENT
|
|---|
| 701 | : '.' ('0'..'9')+ ('E' | 'e' | 'd' | 'D') ('+' | '-')? ('0'..'9')+
|
|---|
| 702 | | '.' ('E' | 'e' | 'd' | 'D') ('+' | '-')? ('0'..'9')+
|
|---|
| 703 | | '.' ('0'..'9')+
|
|---|
| 704 | | ('0'..'9')+ ('e' | 'E' | 'd' | 'D') ('+' | '-')? ('0'..'9')+
|
|---|
| 705 | ;
|
|---|
| 706 |
|
|---|
| 707 | T_PERIOD : '.' ;
|
|---|
| 708 |
|
|---|
| 709 | // begin keyword section (all keywords must appear between
|
|---|
| 710 | // T_BEGIN_KEYWORDS and T_END_KEYWORDS)
|
|---|
| 711 | //
|
|---|
| 712 | T_BEGIN_KEYWORDS: '__BEGIN_KEYWORDS__';
|
|---|
| 713 |
|
|---|
| 714 | T_INTEGER : 'INTEGER' ;
|
|---|
| 715 | T_REAL : 'REAL' ;
|
|---|
| 716 | T_COMPLEX : 'COMPLEX' ;
|
|---|
| 717 | T_CHARACTER : 'CHARACTER' ;
|
|---|
| 718 | T_LOGICAL : 'LOGICAL' ;
|
|---|
| 719 |
|
|---|
| 720 | T_ABSTRACT : 'ABSTRACT' ;
|
|---|
| 721 | T_ACQUIRED_LOCK : 'ACQUIRED_LOCK' ; /* F2008 token */
|
|---|
| 722 | T_ALL : 'ALL' ; /* F2008 token (also in F2003?) */
|
|---|
| 723 | T_ALLOCATABLE : 'ALLOCATABLE' ;
|
|---|
| 724 | T_ALLOCATE : 'ALLOCATE' ;
|
|---|
| 725 | T_ASSIGNMENT : 'ASSIGNMENT' ;
|
|---|
| 726 | // ASSIGN statements are a deleted feature.
|
|---|
| 727 | T_ASSIGN : 'ASSIGN' ;
|
|---|
| 728 | T_ASSOCIATE : 'ASSOCIATE' ;
|
|---|
| 729 | T_ASYNCHRONOUS : 'ASYNCHRONOUS' ;
|
|---|
| 730 | T_BACKSPACE : 'BACKSPACE' ;
|
|---|
| 731 | T_BLOCK : 'BLOCK' ;
|
|---|
| 732 | T_BLOCKDATA : 'BLOCKDATA' ;
|
|---|
| 733 | T_CALL : 'CALL' ;
|
|---|
| 734 | T_CASE : 'CASE' ;
|
|---|
| 735 | T_CLASS : 'CLASS' ;
|
|---|
| 736 | T_CLOSE : 'CLOSE' ;
|
|---|
| 737 | T_CODIMENSION : 'CODIMENSION' ;
|
|---|
| 738 | T_COMMON : 'COMMON' ;
|
|---|
| 739 | T_CONCURRENT : 'CONCURRENT' ;
|
|---|
| 740 | T_CONTAINS : 'CONTAINS' ;
|
|---|
| 741 | T_CONTIGUOUS : 'CONTIGUOUS' ;
|
|---|
| 742 | T_CONTINUE : 'CONTINUE' ;
|
|---|
| 743 | T_CRITICAL : 'CRITICAL' ;
|
|---|
| 744 | T_CYCLE : 'CYCLE' ;
|
|---|
| 745 | T_DATA : 'DATA' ;
|
|---|
| 746 | T_DEFAULT : 'DEFAULT' ;
|
|---|
| 747 | T_DEALLOCATE : 'DEALLOCATE' ;
|
|---|
| 748 | T_DEFERRED : 'DEFERRED' ;
|
|---|
| 749 | T_DO : 'DO' ;
|
|---|
| 750 | T_DOUBLE : 'DOUBLE' ;
|
|---|
| 751 | T_DOUBLEPRECISION: 'DOUBLEPRECISION' ;
|
|---|
| 752 | T_DOUBLECOMPLEX: 'DOUBLECOMPLEX' ;
|
|---|
| 753 | T_ELEMENTAL : 'ELEMENTAL' ;
|
|---|
| 754 | T_ELSE : 'ELSE' ;
|
|---|
| 755 | T_ELSEIF : 'ELSEIF' ;
|
|---|
| 756 | T_ELSEWHERE : 'ELSEWHERE' ;
|
|---|
| 757 | T_ENTRY : 'ENTRY' ;
|
|---|
| 758 | T_ENUM : 'ENUM' ;
|
|---|
| 759 | T_ENUMERATOR : 'ENUMERATOR' ;
|
|---|
| 760 | T_ERROR : 'ERROR' ;
|
|---|
| 761 | T_EQUIVALENCE : 'EQUIVALENCE' ;
|
|---|
| 762 | T_EXIT : 'EXIT' ;
|
|---|
| 763 | T_EXTENDS : 'EXTENDS' ;
|
|---|
| 764 | T_EXTERNAL : 'EXTERNAL' ;
|
|---|
| 765 | T_FILE : 'FILE' ;
|
|---|
| 766 | T_FINAL : 'FINAL' ;
|
|---|
| 767 | T_FLUSH : 'FLUSH' ;
|
|---|
| 768 | T_FORALL : 'FORALL' ;
|
|---|
| 769 | T_FORMAT : 'FORMAT' { inFormat = true; };
|
|---|
| 770 | T_FORMATTED : 'FORMATTED' ;
|
|---|
| 771 | T_FUNCTION : 'FUNCTION' ;
|
|---|
| 772 | T_GENERIC : 'GENERIC' ;
|
|---|
| 773 | T_GO : 'GO' ;
|
|---|
| 774 | T_GOTO : 'GOTO' ;
|
|---|
| 775 | T_IF : 'IF' ;
|
|---|
| 776 | T_IMAGES : 'IMAGES' ;
|
|---|
| 777 | T_IMPLICIT : 'IMPLICIT' ;
|
|---|
| 778 | T_IMPORT : 'IMPORT' ;
|
|---|
| 779 | T_IN : 'IN' ;
|
|---|
| 780 | T_INOUT : 'INOUT' ;
|
|---|
| 781 | T_INTENT : 'INTENT' ;
|
|---|
| 782 | T_INTERFACE : 'INTERFACE' ;
|
|---|
| 783 | T_INTRINSIC : 'INTRINSIC' ;
|
|---|
| 784 | T_INQUIRE : 'INQUIRE' ;
|
|---|
| 785 | T_LOCK : 'LOCK' ; /* F2008 token */
|
|---|
| 786 | T_MEMORY : 'MEMORY' ;
|
|---|
| 787 | T_MODULE : 'MODULE' ;
|
|---|
| 788 | T_NAMELIST : 'NAMELIST' ;
|
|---|
| 789 | T_NONE : 'NONE' ;
|
|---|
| 790 | T_NON_INTRINSIC : 'NON_INTRINSIC' ;
|
|---|
| 791 | T_NON_OVERRIDABLE: 'NON_OVERRIDABLE';
|
|---|
| 792 | T_NOPASS : 'NOPASS' ;
|
|---|
| 793 | T_NULLIFY : 'NULLIFY' ;
|
|---|
| 794 | T_ONLY : 'ONLY' ;
|
|---|
| 795 | T_OPEN : 'OPEN' ;
|
|---|
| 796 | T_OPERATOR : 'OPERATOR' ;
|
|---|
| 797 | T_OPTIONAL : 'OPTIONAL' ;
|
|---|
| 798 | T_OUT : 'OUT' ;
|
|---|
| 799 | T_PARAMETER : 'PARAMETER' ;
|
|---|
| 800 | T_PASS : 'PASS' ;
|
|---|
| 801 | T_PAUSE : 'PAUSE' ;
|
|---|
| 802 | T_POINTER : 'POINTER' ;
|
|---|
| 803 | T_PRINT : 'PRINT' ;
|
|---|
| 804 | T_PRECISION : 'PRECISION' ;
|
|---|
| 805 | T_PRIVATE : 'PRIVATE' ;
|
|---|
| 806 | T_PROCEDURE : 'PROCEDURE' ;
|
|---|
| 807 | T_PROGRAM : 'PROGRAM' ;
|
|---|
| 808 | T_PROTECTED : 'PROTECTED' ;
|
|---|
| 809 | T_PUBLIC : 'PUBLIC' ;
|
|---|
| 810 | T_PURE : 'PURE' ;
|
|---|
| 811 | T_READ : 'READ' ;
|
|---|
| 812 | T_RECURSIVE : 'RECURSIVE' ;
|
|---|
| 813 | T_RESULT : 'RESULT' ;
|
|---|
| 814 | T_RETURN : 'RETURN' ;
|
|---|
| 815 | T_REWIND : 'REWIND' ;
|
|---|
| 816 | T_SAVE : 'SAVE' ;
|
|---|
| 817 | T_SELECT : 'SELECT' ;
|
|---|
| 818 | T_SELECTCASE : 'SELECTCASE' ;
|
|---|
| 819 | T_SELECTTYPE : 'SELECTTYPE' ;
|
|---|
| 820 | T_SEQUENCE : 'SEQUENCE' ;
|
|---|
| 821 | T_STOP : 'STOP' ;
|
|---|
| 822 | T_SUBMODULE : 'SUBMODULE' ;
|
|---|
| 823 | T_SUBROUTINE : 'SUBROUTINE' ;
|
|---|
| 824 | T_SYNC : 'SYNC' ; /* F2008 token */
|
|---|
| 825 | T_TARGET : 'TARGET' ;
|
|---|
| 826 | T_THEN : 'THEN' ;
|
|---|
| 827 | T_TO : 'TO' ;
|
|---|
| 828 | T_TYPE : 'TYPE' ;
|
|---|
| 829 | T_UNFORMATTED : 'UNFORMATTED' ;
|
|---|
| 830 | T_UNLOCK : 'UNLOCK' ; /* F2008 token */
|
|---|
| 831 | T_USE : 'USE' ;
|
|---|
| 832 | T_VALUE : 'VALUE' ;
|
|---|
| 833 | T_VOLATILE : 'VOLATILE' ;
|
|---|
| 834 | T_WAIT : 'WAIT' ;
|
|---|
| 835 | T_WHERE : 'WHERE' ;
|
|---|
| 836 | T_WHILE : 'WHILE' ;
|
|---|
| 837 | T_WRITE : 'WRITE' ;
|
|---|
| 838 |
|
|---|
| 839 | // begin Rice additions --------------------------
|
|---|
| 840 | T_WITHTEAM : 'WITHTEAM' ;
|
|---|
| 841 | T_WITH : 'WITH' ;
|
|---|
| 842 | T_TEAM : 'TEAM' ;
|
|---|
| 843 | T_TOPOLOGY : 'TOPOLOGY' ;
|
|---|
| 844 | T_EVENT : 'EVENT' ;
|
|---|
| 845 | T_LOCKSET : 'LOCKSET' ;
|
|---|
| 846 | T_FINISH : 'FINISH' ;
|
|---|
| 847 | T_SPAWN : 'SPAWN' ;
|
|---|
| 848 | T_COPOINTER : 'COPOINTER' ;
|
|---|
| 849 | T_COTARGET : 'COTARGET' ;
|
|---|
| 850 | // end Rice additions ----------------------------
|
|---|
| 851 |
|
|---|
| 852 | // these tokens (without blank characters) are from 3.3.2.2
|
|---|
| 853 | //
|
|---|
| 854 |
|
|---|
| 855 | T_ENDASSOCIATE : 'ENDASSOCIATE' ;
|
|---|
| 856 | T_ENDBLOCK : 'ENDCOTARGETBLOCK' ;
|
|---|
| 857 | T_ENDBLOCKDATA : 'ENDBLOCKDATA' ;
|
|---|
| 858 | T_ENDCRITICAL : 'ENDCRITICAL' ;
|
|---|
| 859 | T_ENDDO : 'ENDDO' ;
|
|---|
| 860 | T_ENDENUM : 'ENDENUM' ;
|
|---|
| 861 | T_ENDFILE : 'ENDFILE' ;
|
|---|
| 862 | T_ENDFORALL : 'ENDFORALL' ;
|
|---|
| 863 | T_ENDFUNCTION : 'ENDFUNCTION' ;
|
|---|
| 864 | T_ENDIF : 'ENDIF' ;
|
|---|
| 865 | T_ENDMODULE : 'ENDMODULE' ;
|
|---|
| 866 | T_ENDINTERFACE : 'ENDINTERFACE' ;
|
|---|
| 867 | T_ENDPROCEDURE : 'ENDPROCEDURE' ;
|
|---|
| 868 | T_ENDPROGRAM : 'ENDPROGRAM' ;
|
|---|
| 869 | T_ENDSELECT : 'ENDSELECT' ;
|
|---|
| 870 | T_ENDSUBMODULE : 'ENDSUBMODULE' ;
|
|---|
| 871 | T_ENDSUBROUTINE : 'ENDSUBROUTINE' ;
|
|---|
| 872 | T_ENDTYPE : 'ENDTYPE' ;
|
|---|
| 873 | T_ENDWHERE : 'ENDWHERE' ;
|
|---|
| 874 |
|
|---|
| 875 | T_END : 'END'
|
|---|
| 876 | ;
|
|---|
| 877 |
|
|---|
| 878 | T_DIMENSION : 'DIMENSION' ;
|
|---|
| 879 |
|
|---|
| 880 | T_KIND : 'KIND' ;
|
|---|
| 881 | T_LEN : 'LEN' ;
|
|---|
| 882 |
|
|---|
| 883 | T_BIND : 'BIND' ;
|
|---|
| 884 |
|
|---|
| 885 | // End keyword section (all keywords must appear between
|
|---|
| 886 | // T_BEGIN_KEYWORDS and T_END_KEYWORDS)
|
|---|
| 887 | //
|
|---|
| 888 | T_END_KEYWORDS : '__END_KEYWORDS__';
|
|---|
| 889 |
|
|---|
| 890 | //
|
|---|
| 891 | // Note: Hollerith constants were deleted in F77; Hollerith edit descriptors
|
|---|
| 892 | // deleted in F95.
|
|---|
| 893 | //
|
|---|
| 894 | T_HOLLERITH : Digit_String 'H'
|
|---|
| 895 | {
|
|---|
| 896 | // If we're inside a format stmt we don't want to process it as
|
|---|
| 897 | // a Hollerith constant because it's most likely an H-edit descriptor.
|
|---|
| 898 | // However, the H-edit descriptor needs processed the same way both
|
|---|
| 899 | // here and in the prepass.
|
|---|
| 900 | StringBuffer hollConst = new StringBuffer();
|
|---|
| 901 | int count = Integer.parseInt($Digit_String.text);
|
|---|
| 902 |
|
|---|
| 903 | for(int i = 0; i < count; i++)
|
|---|
| 904 | hollConst = hollConst.append((char)input.LA(i+1));
|
|---|
| 905 | for(int i = 0; i < count; i++)
|
|---|
| 906 | // consume the character so the lexer doesn't try matching it.
|
|---|
| 907 | input.consume();
|
|---|
| 908 | };
|
|---|
| 909 |
|
|---|
| 910 | // Must come after .EQ. (for example) or will get matched first
|
|---|
| 911 | // TODO:: this may have to be done in the parser w/ a rule such as:
|
|---|
| 912 | // T_PERIOD T_IDENT T_PERIOD
|
|---|
| 913 | T_DEFINED_OP
|
|---|
| 914 | : '.' Letter+ '.'
|
|---|
| 915 | ;
|
|---|
| 916 |
|
|---|
| 917 | // // used to catch edit descriptors and other situations
|
|---|
| 918 | // T_ID_OR_OTHER
|
|---|
| 919 | // : 'ID_OR_OTHER'
|
|---|
| 920 | // ;
|
|---|
| 921 |
|
|---|
| 922 | // extra, context-sensitive terminals that require communication between parser and scanner
|
|---|
| 923 | // added the underscores so there is no way this could overlap w/ any valid
|
|---|
| 924 | // idents in Fortran. we just need this token to be defined so we can
|
|---|
| 925 | // create one of them while we're fixing up labeled do stmts.
|
|---|
| 926 | T_LABEL_DO_TERMINAL
|
|---|
| 927 | : '__LABEL_DO_TERMINAL__'
|
|---|
| 928 | ;
|
|---|
| 929 |
|
|---|
| 930 | T_DATA_EDIT_DESC : '__T_DATA_EDIT_DESC__' ;
|
|---|
| 931 | T_CONTROL_EDIT_DESC : '__T_CONTROL_EDIT_DESC__' ;
|
|---|
| 932 | T_CHAR_STRING_EDIT_DESC : '__T_CHAR_STRING_EDIT_DESC__' ;
|
|---|
| 933 |
|
|---|
| 934 | T_STMT_FUNCTION
|
|---|
| 935 | : 'STMT_FUNCTION'
|
|---|
| 936 | ;
|
|---|
| 937 |
|
|---|
| 938 | T_ASSIGNMENT_STMT : '__T_ASSIGNMENT_STMT__' ;
|
|---|
| 939 | T_PTR_ASSIGNMENT_STMT : '__T_PTR_ASSIGNMENT_STMT__' ;
|
|---|
| 940 | T_ARITHMETIC_IF_STMT : '__T_ARITHMETIC_IF_STMT__' ;
|
|---|
| 941 | T_ALLOCATE_STMT_1 : '__T_ALLOCATE_STMT_1__' ;
|
|---|
| 942 | T_WHERE_STMT : '__T_WHERE_STMT__' ;
|
|---|
| 943 | T_IF_STMT : '__T_IF_STMT__' ;
|
|---|
| 944 | T_FORALL_STMT : '__T_FORALL_STMT__' ;
|
|---|
| 945 | T_WHERE_CONSTRUCT_STMT : '__T_WHERE_CONSTRUCT_STMT__' ;
|
|---|
| 946 | T_FORALL_CONSTRUCT_STMT : '__T_FORALL_CONSTRUCT_STMT__' ;
|
|---|
| 947 | T_INQUIRE_STMT_2 : '__T_INQUIRE_STMT_2__' ;
|
|---|
| 948 | // text for the real constant will be set when a token of this type is
|
|---|
| 949 | // created by the prepass.
|
|---|
| 950 | T_REAL_CONSTANT : '__T_REAL_CONSTANT__' ;
|
|---|
| 951 |
|
|---|
| 952 | T_INCLUDE_NAME: '__T_INCLUDE_NAME__' ;
|
|---|
| 953 | T_EOF: '__T_EOF__' ;
|
|---|
| 954 |
|
|---|
| 955 | // R304
|
|---|
| 956 | T_IDENT
|
|---|
| 957 | options {k=1;}
|
|---|
| 958 | : Letter ( Alphanumeric_Character )*
|
|---|
| 959 | ;
|
|---|
| 960 |
|
|---|
| 961 | //
|
|---|
| 962 | // Used in format-item processing. This token is replaced by an edit
|
|---|
| 963 | // descriptor in the prepass (by FortranLexicalPrepass). It doesn't really
|
|---|
| 964 | // matter what this token contains because the format string is parsed
|
|---|
| 965 | // as a string in the lexical prepass. The goal is to keep the lexer from
|
|---|
| 966 | // bombing on strings like 2es15.6 and also not interfer with real literal
|
|---|
| 967 | // constants and Holleriths.
|
|---|
| 968 | //
|
|---|
| 969 | T_EDIT_DESC_MISC
|
|---|
| 970 | : Digit_String
|
|---|
| 971 | ( ('e'|'E') (('n'|'N') | ('s'|'S')) )
|
|---|
| 972 | ( Alphanumeric_Character )*
|
|---|
| 973 | ;
|
|---|
| 974 |
|
|---|
| 975 | LINE_COMMENT
|
|---|
| 976 | : '!' ~('\n'|'\r'|'$')*
|
|---|
| 977 | {
|
|---|
| 978 | $channel = HIDDEN;
|
|---|
| 979 | }
|
|---|
| 980 | ;
|
|---|
| 981 |
|
|---|
| 982 | /* Need a catch-all rule because of fixed-form being allowed to use any
|
|---|
| 983 | character in column 6 to designate a continuation. */
|
|---|
| 984 | MISC_CHAR : ~('\n' | '\r') ;
|
|---|
| 985 |
|
|---|
| 986 | T_PRAGMA
|
|---|
| 987 | : '!$'
|
|---|
| 988 | ; |
|---|