lex.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 317 行
C
317 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
//
// LEX : lexical analyser
//
#include "ftnstd.h"
#include "opr.h"
#include "opn.h"
#include "errcod.h"
#include "stmtsw.h"
#include "progsw.h"
#include "global.h"
#include "ferror.h"
#include "frl.h"
#include "comio.h"
#include <string.h>
extern void InitScan(void);
extern void Scan(void);
extern char *StmtKeywords[];
extern char *LogTab[];
#define LOG_OPS 11
#define XLOG_OPS 11
static const OPR __FAR LogOpr[] = { // must correspond to table in SCAN
OPR_EQ, OPR_NE, OPR_LT, OPR_GT, OPR_LE, OPR_GE,
OPR_OR, OPR_AND, OPR_NOT, OPR_EQV, OPR_NEQV, OPR_NEQV,
OPR_PHI, OPR_PHI, OPR_PHI
};
static itnode *NewITNode( void ) {
//==================================
// Create a new itnode.
itnode *new;
new = FrlAlloc( &ITPool, sizeof( itnode ) );
if( new != NULL ) {
new->opnd = Lex.ptr;
new->opnd_size = Lex.len;
new->opr = Lex.opr;
new->oprpos = Lex.oprpos;
new->opn.ds = Lex.opn.ds;
new->opnpos = Lex.opnpos;
new->link = NULL;
new->list = NULL;
new->flags = 0;
new->typ = TY_NO_TYPE;
new->chsize = 0;
new->is_unsigned = 0;
new->is_catparen = 0;
}
return( new );
}
void MakeITList( void ) {
//====================
// Make up the internal text list.
itnode *new_it;
InitScan();
Lex.opr = OPR_TRM;
Lex.oprpos = ( LexToken.line << 8 ) + LexToken.col + 1;
Scan();
if( !(LexToken.flags & TK_EOL) ) {
if( LexToken.col < CONT_COL - 1 ) {
Error( CC_NOT_DIGITS );
}
}
BrCnt = 0;
SPtr1 = NULL;
SPtr2 = NULL;
GetOpnd();
ITHead = NewITNode();
if( ITHead == NULL ) {
FlushStatement();
return;
}
CITNode = ITHead;
for(;;) {
if( LexToken.flags & TK_EOL ) break;
GetOpr();
GetOpnd();
// Consider what happens when NewITNode() calls FrlAlloc() who
// in turns calls FMemAlloc() and there is no memory left.
// FMemAlloc() frees the I.T. list starting at ITHead so when
// we return CITNode has been freed.
// So don't code ----> CITNode->link = NewITNode();
new_it = NewITNode();
if( new_it == NULL ) {
FlushStatement();
return;
}
CITNode->link = new_it;
CITNode = CITNode->link;
SetSwitch();
}
// If the last token in the statement is a NULL operand, then
// make the caret point 1 past the operator. Otherwise
// it will point at the end of the line and for fixed-length
// files which contain trailing blanks this will look funny.
if( CITNode->opn.ds == DSOPN_PHI ) {
CITNode->opnpos = CITNode->oprpos + 1;
}
if( BrCnt != 0 ) {
Error( PC_NO_CLOSEPAREN );
}
Lex.opr = OPR_TRM;
Lex.opn.ds = DSOPN_PHI;
Lex.oprpos = 9999;
Lex.opnpos = 9999;
Lex.len = 0;
new_it = NewITNode();
if( new_it == NULL ) {
FlushStatement();
return;
}
CITNode->link = new_it;
CITNode->link->link = NULL;
CITNode = ITHead;
}
static void FlushStatement( void ) {
//========================================
for(;;) {
ComRead();
if( ( ProgSw & PS_SOURCE_EOF ) != 0 ) break;
if( StmtType != STMT_CONT ) break;
ComPrint();
}
}
static void SetSwitch( void ) {
//===========================
// Set statement switches according to operators.
if( Lex.opr == OPR_LBR ) {
++BrCnt;
} else if( Lex.opr == OPR_RBR ) {
--BrCnt;
if( BrCnt < 0 ) {
Error( PC_UNMATCH_PAREN );
BrCnt = 0;
} else if( BrCnt == 0 ) {
if( SPtr1 == NULL ) {
SPtr1 = CITNode;
} else if( SPtr2 == NULL ) {
SPtr2 = CITNode;
}
}
} else if( BrCnt == 0 ) {
if( Lex.opr == OPR_COM ) {
if( ( StmtSw & SS_EQUALS_FOUND ) != 0 ) {
StmtSw |= SS_EQ_THEN_COMMA;
} else {
StmtSw |= SS_COMMA_FOUND;
}
} else if( Lex.opr == OPR_EQU ) {
if( ( StmtSw & SS_COMMA_FOUND ) != 0 ) {
StmtSw |= SS_COMMA_THEN_EQ;
} else {
StmtSw |= SS_EQUALS_FOUND;
}
}
}
}
static OPR LkUpOpr( void ) {
//=========================
switch( *LexToken.start ) {
case ',': return( OPR_COM );
case '(': return( OPR_LBR );
case ')': return( OPR_RBR );
case '=': return( OPR_EQU );
case '/': return( OPR_DIV );
case '*': return( OPR_MUL );
case '-': return( OPR_MIN );
case '+': return( OPR_PLS );
case ':': return( OPR_COL );
case '%': return( OPR_FLD );
case '.': return( OPR_DPT );
}
Error( SX_INV_OPR );
return( OPR_PHI );
}
static void GetOpr( void ) {
//========================
// Collect an operator.
Lex.oprpos = ( LexToken.line << 8 ) + LexToken.col + 1;
if( LexToken.class == TO_OPR ) {
Lex.opr = LkUpOpr();
// this is to tell scan not to collect
// 4d4 in INTEGER*4 d4,a,b . . .
// 4h,a,b in INTEGER*4 h,a,b . . .
LexToken.flags &= ~TK_LENSPEC;
if( ( Lex.opr == OPR_MUL ) && ( CITNode == ITHead ) ) {
LexToken.flags |= TK_LENSPEC;
}
Scan();
if( ( LexToken.class == TO_OPR ) && !(LexToken.flags & TK_EOL) &&
( ( Lex.opr == OPR_MUL ) || ( Lex.opr == OPR_DIV ) ) &&
( Lex.opr == LkUpOpr() ) ) {
if( Lex.opr == OPR_MUL ) {
Lex.opr = OPR_EXP;
} else {
Lex.opr = OPR_CAT;
}
Scan();
}
} else if( LexToken.class == TO_LGL ) {
Lex.opr = LogOpr[ LexToken.log ];
if( LexToken.log >= XLOG_OPS ) {
Extension( MD_LOGOPR_EXTN, LogTab[ LexToken.log ] );
}
Scan();
} else {
Lex.opr = OPR_PHI;
}
}
static void GetOpnd( void ) {
//=========================
// Scan off an operand.
char *kw;
Lex.ptr = LexToken.start;
Lex.opnpos = ( LexToken.line << 8 ) + LexToken.col + 1;
if( LexToken.class == TO_OPR ) {
Lex.opn.ds = DSOPN_PHI;
Lex.len = 0;
} else if( LexToken.class == TO_LGL ) {
if( LexToken.log > LOG_OPS ) {
Lex.len = LexToken.stop - LexToken.start;
Lex.opn.ds = DSOPN_LGL;
Scan();
} else {
Lex.len = 0;
Lex.opn.ds = DSOPN_PHI;
}
} else {
Lex.len = LexToken.stop - LexToken.start;
Lex.opn.ds = LexToken.class;
// this is a kludge to collect FORMAT/INCLUDE statements
// we don't want INCLUDE statements to span lines
if( (ITHead == NULL) && (Lex.opr == OPR_TRM) && (Lex.opn.ds == DSOPN_NAM) ) {
if( Lex.len == 6 ) {
if( ( Cursor == NULL ) || ( *Cursor == '(' ) ) {
kw = StmtKeywords[ PR_FMT ];
if( memcmp( LexToken.start, kw, 6 ) == 0 ) {
State = SFM;
}
}
} else if( Lex.len == 7 ) {
if( ( Cursor != NULL ) && ( *Cursor == '\'' ) ) {
kw = StmtKeywords[ PR_INCLUDE ];
if( memcmp( LexToken.start, kw, 7 ) == 0 ) {
LexToken.flags |= TK_INCLUDE;
}
}
}
}
// end of kludge
Scan();
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?