📄 lexer.c
字号:
#include "lexer.h"
// syntaxError:
// Display a SYNTAX ERROR message and exit.
void syntaxError( char *msg )
{
fprintf( stderr, "SYNTAX ERROR: " );
error( msg );
}//syntaxError
// lex:
// Generate the APT (Abstract Parse Tree) for a
// language block (until TAG_SCRIPT has reached).
struct lisa_node *lex( unsigned int scope )
{
lisa_node *node;
lisa_node *next;
lisa_node *work;
lisa_node *tmp;
char *element;
// get a token
node = parse();
element = node->element;
switch ( node->type )
{
case LISA_TYPE_OPEN_BLOCK_BRACKET:
{
if ( ! ( scope & LISA_SCOPE_BLOCK ) )
{
// return an empty node if EMPTY required...
if ( scope & LISA_SCOPE_EMPTY )
{
pushbackNode( node );
return createNode();
}
// else, stop compiling...
syntaxError( "no '{' required" );
}
// destroy this node...
destroyNode( node );
// parse for INSTRUCTION...
node = lex( LISA_SCOPE_STATEMENT | LISA_SCOPE_EXPRESSION );
// parse for optional INSTRUCTIONS...
next = node;
while( 1 )
{
// checking for '}'...
work = parse();
if ( work->type != LISA_TYPE_CLOSE_BLOCK_BRACKET )
{
pushbackNode( work );
}
else
{
destroyNode( work );
break;
}
// parse for INSTRUCTION...
work = lex( LISA_SCOPE_STATEMENT | LISA_SCOPE_EXPRESSION );
next->next = work;
next = work;
}
break;
}
case LISA_TYPE_OPEN_ROUND_BRACKET:
{
if ( ! ( scope & ( LISA_SCOPE_ARGUMENTS | LISA_SCOPE_EXPRESSION | LISA_SCOPE_CONDITION ) ) )
{
// return an empty node if EMPTY required...
if ( scope & LISA_SCOPE_EMPTY )
{
pushbackNode( node );
return createNode();
}
// else, stop compiling...
syntaxError( "no '(' required" );
}
if ( scope & LISA_SCOPE_ARGUMENTS )
{
// APT:
//
// caller
// / |
// '(' ...
// /
// [ arglist ]
//
// parse for optional args lins...
work = lex( LISA_SCOPE_CONDITION | LISA_SCOPE_EMPTY );
if ( emptyNode( work ) )
{
destroyNode( work );
work = NULL;
}
node->args = work;
// checking for ')'...
work = parse();
if ( work->type != LISA_TYPE_CLOSE_ROUND_BRACKET )
{
syntaxError( "missed ')'" );
}
}
else
{
node->type = LISA_TYPE_EXPRESSION;
// get the rest of expression/condition...
work = lex( LISA_SCOPE_CONDITION );
node->args = work;
// checking for ')'...
work = parse();
if ( work->type != LISA_TYPE_CLOSE_ROUND_BRACKET )
{
syntaxError( "missed ')'" );
}
// parse for optional operator...
work = parse();
if ( work->type == LISA_TYPE_OPERATOR )
{
node->next = work;
}
else
{
pushbackNode( work );
if ( scope & LISA_SCOPE_EXPRESSION )
work = lex( LISA_SCOPE_SEMICOLON );
break;
}
work = lex( LISA_SCOPE_CONDITION | LISA_SCOPE_EMPTY );
if ( emptyNode( work ) )
{
destroyNode( work );
work = NULL;
}
node->next->next = work;
if ( scope & LISA_SCOPE_EXPRESSION )
lex( LISA_SCOPE_SEMICOLON );
}
// NOTE: (2002-06-20 Gabriele Budelacci)
// Returning a '(' node in every case...
break;
}
case LISA_TYPE_OPEN_SQUARE_BRACKET:
{
if ( ! ( scope & LISA_SCOPE_INDEX ) )
{
// return an empty node if EMPTY required...
if ( scope & LISA_SCOPE_EMPTY )
{
pushbackNode( node );
return createNode();
}
// else, stop compiling...
syntaxError( "no '[' required" );
}
// APT:
//
// caller
// / |
// '[' ...
// /
// [ expression ]
//
// parse for optional index EXPRESSION...
work = lex( LISA_SCOPE_CONDITION | LISA_SCOPE_EMPTY );
if ( emptyNode( work ) )
{
destroyNode( work );
work = NULL;
}
node->args = work;
// checking for ']'...
work = parse();
if ( work->type != LISA_TYPE_CLOSE_SQUARE_BRACKET )
{
syntaxError( "missed ']'" );
}
// NOTE: (2002-06-20 Gabriele Budelacci)
// Returning a '[' node in every case...
break;
}
case LISA_TYPE_COLON:
{
if ( ! ( scope & LISA_SCOPE_COLON ) )
{
// return an empty node if EMPTY required...
if ( scope & LISA_SCOPE_EMPTY )
{
pushbackNode( node );
return createNode();
}
// else, stop compiling...
syntaxError( "no ':' required" );
}
break;
}
case LISA_TYPE_IDENTIFIER:
{
if ( ! ( scope & ( LISA_SCOPE_EXPRESSION | LISA_SCOPE_CONDITION ) ) )
{
// return an empty node if EMPTY required...
if ( scope & LISA_SCOPE_EMPTY )
{
pushbackNode( node );
return createNode();
}
// else, stop compiling...
syntaxError( "no identifier required" );
}
// check for arg list => this is a function call...
work = lex( LISA_SCOPE_ARGUMENTS | LISA_SCOPE_EMPTY );
if ( emptyNode( work ) )
{
// not a function call...
destroyNode( work );
// check for index expression => this is an array value...
work = lex( LISA_SCOPE_INDEX | LISA_SCOPE_EMPTY );
if ( emptyNode( work ) )
{
// not an array...
destroyNode( work );
}
else
{
// array value...
node->args = work->args;
destroyNode( work );
node->type = LISA_TYPE_ARRAY;
}
}
else
{
// function call...
node->args = work;
node->type = LISA_TYPE_FUNCTION;
}
// parse for optional operator...
work = parse();
if ( work->type == LISA_TYPE_OPERATOR )
{
node->next = work;
}
else
{
pushbackNode( work );
if ( scope & LISA_SCOPE_EXPRESSION )
{
work = lex( LISA_SCOPE_SEMICOLON );
destroyNodeR( work );
// creating empty expression node...
work = createNode();
work->type = LISA_TYPE_EXPRESSION;
// ...and returning it...
work->args = node;
node = work;
}
break;
}
work = lex( LISA_SCOPE_CONDITION | LISA_SCOPE_EMPTY );
if ( emptyNode( work ) )
{
destroyNode( work );
work = NULL;
}
node->next->next = work;
if ( scope & LISA_SCOPE_EXPRESSION )
{
work = lex( LISA_SCOPE_SEMICOLON );
destroyNodeR( work );
// creating empty expression node...
work = createNode();
work->type = LISA_TYPE_EXPRESSION;
// ...and returning it...
work->args = node;
node = work;
}
break;
}
case LISA_TYPE_DIRECTIVE:
{
// NOTE: (2002-06-21 Gabriele Budelacci)
// Im searching for a DIRECTIVE, but I accept
// a STATEMENT now...
if ( ! ( scope & LISA_SCOPE_STATEMENT ) )
{
// return an empty node if EMPTY required...
if ( scope & LISA_SCOPE_EMPTY )
{
pushbackNode( node );
return createNode();
}
// else, stop compiling...
syntaxError( "no directive required" );
}
// #include "filename"
//
// #include
// / |
// "filename" ...
//
// #include <modulename> (alternative syntax)
//
// #include
// / |
// modulename ...
//
if ( strcmp( node->element, "#include" ) == 0 )
{
// parse for filename or modulename...
work = parse();
if ( work->type != LISA_TYPE_STRING )
{
if ( strcmp( work->element, "<" ) != 0 )
{
syntaxError( "filename or modulename required" );
}
destroyNode( work );
// get modulename...
work = parse();
if ( work->type != LISA_TYPE_IDENTIFIER )
{
syntaxError( "bad or missing modulename" );
}
node->args = work;
// get '>'...
work = parse();
if ( strcmp( work->element, ">" ) != 0 )
{
syntaxError( "'>' required" );
}
destroyNode( work );
// restore a good value for work...
work = node->args;
}
node->args = work;
break;
}
// #php .. #/php
//
// #php
// / |
// php section ...
//
if ( strcmp( node->element, "#php" ) == 0 )
{
// NOTE: (2002-07-03 Gabriele Budelacci)
// This part of code is performed by parser.
break;
}
break;
}
case LISA_TYPE_KEYWORD:
{
if ( ! ( scope & LISA_SCOPE_STATEMENT ) )
{
// return an empty node if EMPTY required...
if ( scope & LISA_SCOPE_EMPTY )
{
pushbackNode( node );
return createNode();
}
// else, stop compiling...
syntaxError( "no statement required" );
}
// break;
if ( strcmp( element, "break" ) == 0 )
{
work = lex( LISA_SCOPE_SEMICOLON );
if ( emptyNode( work ) )
syntaxError( "missing ';'" );
break;
}
// array identifier {, identifier};
// set identifier {, identifier};
// var identifier {, identifier};
//
// array
// / |
// identifier ...
// |
// { identifier }
//
if ( ( strcmp( element, "array" ) == 0 ) ||
( strcmp( element, "set" ) == 0 ) ||
( strcmp( element, "var" ) == 0 ) )
{
// parse for identifier...
work = parse();
if ( work->type != LISA_TYPE_IDENTIFIER )
syntaxError( "missing identifier" );
node->args = work;
// parsing for optional declaration list...
next = work;
work = parse();
while ( strcmp( work->element, "," ) == 0 )
{
// destroy ',' token
destroyNode( work );
// parse for identifier...
work = parse();
if ( work->type != LISA_TYPE_IDENTIFIER )
syntaxError( "missing identifier" );
next->next = work;
next = work;
// check if ","
work = parse();
}
pushbackNode( work );
work = lex( LISA_SCOPE_SEMICOLON );
if ( emptyNode( work ) )
syntaxError( "missing ';'" );
break;
}
// case value:
//
// case
// /|
// value
//
if ( strcmp( element, "case" ) == 0 )
{
node->type = LISA_TYPE_TAGKEYWORD;
//parsing for value...
work = parse();
if ( ( work->type != LISA_TYPE_NUMBER ) &&
( work->type != LISA_TYPE_STRING ) )
syntaxError( "missing fixed value" );
node->args = work;
// parse for ':'...
work = lex( LISA_SCOPE_COLON );
destroyNode( work );
break;
}
// continue;
if ( strcmp( element, "continue" ) == 0 )
{
work = lex( LISA_SCOPE_SEMICOLON );
if ( emptyNode( work ) )
syntaxError( "missing ';'" );
break;
}
// default:
// else:
if ( ( strcmp( element, "default" ) == 0 ) ||
( strcmp( element, "else" ) == 0 ) )
{
node->type = LISA_TYPE_TAGKEYWORD;
// parse for ':'...
work = lex( LISA_SCOPE_COLON );
destroyNode( work );
break;
}
// endif;
// endforeach;
// endswitch;
// endwhile;
// next;
if ( ( strcmp( element, "endif" ) == 0 ) ||
( strcmp( element, "endforeach" ) == 0 ) ||
( strcmp( element, "endswitch" ) == 0 ) ||
( strcmp( element, "endwhile" ) == 0 ) ||
( strcmp( element, "next" ) == 0 ) )
{
node->type = LISA_TYPE_TAGKEYWORD;
// a ';' is required at end of statement
work = lex( LISA_SCOPE_SEMICOLON );
destroyNode( work );
break;
}
// foreach ( set-identifier as identifier {, identifier} )
// block
//
// foreach ( array-identifier as identifier )
// block
//
// foreach
// / |
// array-set-identifier ...
// / |
// block { identifier }
//
if ( strcmp( element, "foreach" ) == 0 )
{
// parse for '('...
work = parse();
if ( work->type != LISA_TYPE_OPEN_ROUND_BRACKET )
syntaxError( "missing '('" );
destroyNode( work );
// parse for set-identifier...
work = parse();
if ( work->type != LISA_TYPE_IDENTIFIER )
syntaxError( "missing set identifier" );
node->args = work;
// parse for as keyword...
work = parse();
if ( work->type != LISA_TYPE_KEYWORD )
syntaxError( "missing 'as' keyword" );
destroyNode( work );
// parse for identifiers...
work = parse();
if ( work->type != LISA_TYPE_IDENTIFIER )
syntaxError( "missing identifier" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -