mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 00:29:31 +00:00
Allow token lists to be optionally enclosed in curly braces. Using such
enclosement, tokens that would otherwise terminate the list can be part of the list. git-svn-id: svn://svn.cc65.org/cc65/trunk@3013 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
df07cf1114
commit
fdb685b874
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* (C) 1998-2004 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -418,15 +418,22 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
|
||||
/* Handle the .MATCH and .XMATCH builtin functions */
|
||||
{
|
||||
int Result;
|
||||
enum Token Term;
|
||||
TokNode* Root = 0;
|
||||
TokNode* Last = 0;
|
||||
TokNode* Node;
|
||||
|
||||
/* A list of tokens follows. Read this list and remember it building a
|
||||
* single linked list of tokens including attributes. The list is
|
||||
* terminated by a comma.
|
||||
* either enclosed in curly braces, or terminated by a comma.
|
||||
*/
|
||||
while (Tok != TOK_COMMA) {
|
||||
if (Tok == TOK_LCURLY) {
|
||||
NextTok ();
|
||||
Term = TOK_RCURLY;
|
||||
} else {
|
||||
Term = TOK_COMMA;
|
||||
}
|
||||
while (Tok != Term) {
|
||||
|
||||
/* We may not end-of-line of end-of-file here */
|
||||
if (TokIsSep (Tok)) {
|
||||
@ -449,15 +456,27 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
/* Skip the comma */
|
||||
/* Skip the terminator token*/
|
||||
NextTok ();
|
||||
|
||||
/* Read the second list which is terminated by the right parenthesis and
|
||||
* compare each token against the one in the first list.
|
||||
/* If the token list was enclosed in curly braces, we expect a comma */
|
||||
if (Term == TOK_RCURLY) {
|
||||
ConsumeComma ();
|
||||
}
|
||||
|
||||
/* Read the second list which is optionally enclosed in curly braces and
|
||||
* terminated by the right parenthesis. Compare each token against the
|
||||
* one in the first list.
|
||||
*/
|
||||
if (Tok == TOK_LCURLY) {
|
||||
NextTok ();
|
||||
Term = TOK_RCURLY;
|
||||
} else {
|
||||
Term = TOK_RPAREN;
|
||||
}
|
||||
Result = 1;
|
||||
Node = Root;
|
||||
while (Tok != TOK_RPAREN) {
|
||||
while (Tok != Term) {
|
||||
|
||||
/* We may not end-of-line of end-of-file here */
|
||||
if (TokIsSep (Tok)) {
|
||||
@ -485,6 +504,11 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
/* If the token list was enclosed in curly braces, eat the closing brace */
|
||||
if (Term == TOK_RCURLY) {
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
/* Check if there are remaining tokens in the first list */
|
||||
if (Node != 0) {
|
||||
Result = 0;
|
||||
|
@ -655,7 +655,9 @@ MacEnd:
|
||||
static void StartExpClassic (Macro* M)
|
||||
/* Start expanding the classic macro M */
|
||||
{
|
||||
MacExp* E;
|
||||
MacExp* E;
|
||||
enum Token Term;
|
||||
|
||||
|
||||
/* Skip the macro name */
|
||||
NextTok ();
|
||||
@ -670,21 +672,29 @@ static void StartExpClassic (Macro* M)
|
||||
|
||||
/* Check for maximum parameter count */
|
||||
if (E->ParamCount >= M->ParamCount) {
|
||||
Error ("Too many macro parameters");
|
||||
SkipUntilSep ();
|
||||
ErrorSkip ("Too many macro parameters");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read tokens for one parameter, accept empty params */
|
||||
/* The macro may optionally be enclosed in curly braces */
|
||||
if (Tok == TOK_LCURLY) {
|
||||
NextTok ();
|
||||
Term = TOK_RCURLY;
|
||||
} else {
|
||||
Term = TOK_COMMA;
|
||||
}
|
||||
|
||||
/* Read tokens for one parameter, accept empty params */
|
||||
Last = 0;
|
||||
while (Tok != TOK_COMMA && Tok != TOK_SEP) {
|
||||
while (Tok != Term && Tok != TOK_SEP) {
|
||||
|
||||
TokNode* T;
|
||||
|
||||
/* Check for end of file */
|
||||
if (Tok == TOK_EOF) {
|
||||
Error ("Unexpected end of file");
|
||||
return;
|
||||
Error ("Unexpected end of file");
|
||||
FreeMacExp (E);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the next token in a node */
|
||||
@ -694,7 +704,7 @@ static void StartExpClassic (Macro* M)
|
||||
if (Last == 0) {
|
||||
E->Params [E->ParamCount] = T;
|
||||
} else {
|
||||
Last->Next = T;
|
||||
Last->Next = T;
|
||||
}
|
||||
Last = T;
|
||||
|
||||
@ -705,14 +715,28 @@ static void StartExpClassic (Macro* M)
|
||||
/* One parameter more */
|
||||
++E->ParamCount;
|
||||
|
||||
/* If the macro argument was enclosed in curly braces, end-of-line
|
||||
* is an error. Skip the closing curly brace.
|
||||
*/
|
||||
if (Term == TOK_RCURLY) {
|
||||
if (Tok == TOK_SEP) {
|
||||
Error ("End of line encountered within macro argument");
|
||||
break;
|
||||
}
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
/* Check for a comma */
|
||||
if (Tok == TOK_COMMA) {
|
||||
NextTok ();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
NextTok ();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We must be at end of line now, otherwise something is wrong */
|
||||
ExpectSep ();
|
||||
|
||||
/* Insert a new token input function */
|
||||
PushInput (MacExpand, E, ".MACRO");
|
||||
}
|
||||
@ -736,14 +760,23 @@ static void StartExpDefine (Macro* M)
|
||||
/* Read the actual parameters */
|
||||
while (Count--) {
|
||||
|
||||
TokNode* Last;
|
||||
enum Token Term;
|
||||
TokNode* Last;
|
||||
|
||||
/* The macro may optionally be enclosed in curly braces */
|
||||
if (Tok == TOK_LCURLY) {
|
||||
NextTok ();
|
||||
Term = TOK_RCURLY;
|
||||
} else {
|
||||
Term = TOK_COMMA;
|
||||
}
|
||||
|
||||
/* Check if there is really a parameter */
|
||||
if (TokIsSep (Tok) || Tok == TOK_COMMA) {
|
||||
Error ("Macro parameter expected");
|
||||
SkipUntilSep ();
|
||||
return;
|
||||
}
|
||||
if (TokIsSep (Tok) || Tok == Term) {
|
||||
ErrorSkip ("Macro parameter #%u is empty", E->ParamCount+1);
|
||||
FreeMacExp (E);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read tokens for one parameter */
|
||||
Last = 0;
|
||||
@ -765,11 +798,22 @@ static void StartExpDefine (Macro* M)
|
||||
/* And skip it... */
|
||||
NextTok ();
|
||||
|
||||
} while (Tok != TOK_COMMA && !TokIsSep (Tok));
|
||||
} while (Tok != Term && !TokIsSep (Tok));
|
||||
|
||||
/* One parameter more */
|
||||
++E->ParamCount;
|
||||
|
||||
/* If the macro argument was enclosed in curly braces, end-of-line
|
||||
* is an error. Skip the closing curly brace.
|
||||
*/
|
||||
if (Term == TOK_RCURLY) {
|
||||
if (TokIsSep (Tok)) {
|
||||
Error ("End of line encountered within macro argument");
|
||||
break;
|
||||
}
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
/* Check for a comma */
|
||||
if (Count > 0) {
|
||||
if (Tok == TOK_COMMA) {
|
||||
@ -782,7 +826,7 @@ static void StartExpDefine (Macro* M)
|
||||
|
||||
/* Macro expansion will overwrite the current token. This is a problem
|
||||
* for define style macros since these are called from the scanner level.
|
||||
* To avoid it, remember the current token and re-insert it if macro
|
||||
* To avoid it, remember the current token and re-insert it, once macro
|
||||
* expansion is done.
|
||||
*/
|
||||
E->Final = NewTokNode ();
|
||||
|
@ -65,18 +65,29 @@ static unsigned RawMode = 0; /* Raw token mode flag/counter */
|
||||
|
||||
|
||||
static TokList* CollectTokens (unsigned Start, unsigned Count)
|
||||
/* Read a list of tokens that is terminated by a right paren. For all tokens
|
||||
* starting at the one with index Start, and ending at (Start+Count-1), place
|
||||
* them into a token list, and return this token list.
|
||||
/* Read a list of tokens that is optionally enclosed in curly braces and
|
||||
* terminated by a right paren. For all tokens starting at the one with index
|
||||
* Start, and ending at (Start+Count-1), place them into a token list, and
|
||||
* return this token list.
|
||||
*/
|
||||
{
|
||||
enum Token Term;
|
||||
unsigned Current;
|
||||
|
||||
/* Create the token list */
|
||||
TokList* List = NewTokList ();
|
||||
|
||||
/* Determine if the list is enclosed in curly braces. */
|
||||
if (Tok == TOK_LCURLY) {
|
||||
NextTok ();
|
||||
Term = TOK_RCURLY;
|
||||
} else {
|
||||
Term = TOK_LCURLY;
|
||||
}
|
||||
|
||||
/* Read the token list */
|
||||
unsigned Current = 0;
|
||||
unsigned Parens = 0;
|
||||
while (Parens != 0 || Tok != TOK_RPAREN) {
|
||||
Current = 0;
|
||||
while (Tok != Term) {
|
||||
|
||||
/* Check for end of line or end of input */
|
||||
if (TokIsSep (Tok)) {
|
||||
@ -90,20 +101,18 @@ static TokList* CollectTokens (unsigned Start, unsigned Count)
|
||||
AddCurTok (List);
|
||||
}
|
||||
|
||||
/* Check for and count parenthesii */
|
||||
if (Tok == TOK_LPAREN) {
|
||||
++Parens;
|
||||
} else if (Tok == TOK_RPAREN) {
|
||||
--Parens;
|
||||
}
|
||||
|
||||
/* Get the next token */
|
||||
++Current;
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
/* Eat the closing paren */
|
||||
ConsumeRParen ();
|
||||
/* Eat the terminator token */
|
||||
NextTok ();
|
||||
|
||||
/* If the list was enclosed in curly braces, we do expect now a right paren */
|
||||
if (Term == TOK_RCURLY) {
|
||||
ConsumeRParen ();
|
||||
}
|
||||
|
||||
/* Return the list of collected tokens */
|
||||
return List;
|
||||
@ -422,7 +431,7 @@ void ConsumeSep (void)
|
||||
/* We expect a separator token */
|
||||
ExpectSep ();
|
||||
|
||||
/* If we have one, skip it */
|
||||
/* If we are at end of line, skip it */
|
||||
if (Tok == TOK_SEP) {
|
||||
NextTok ();
|
||||
}
|
||||
|
@ -980,6 +980,16 @@ CharAgain:
|
||||
Tok = TOK_RBRACK;
|
||||
return;
|
||||
|
||||
case '{':
|
||||
NextChar ();
|
||||
Tok = TOK_LCURLY;
|
||||
return;
|
||||
|
||||
case '}':
|
||||
NextChar ();
|
||||
Tok = TOK_RCURLY;
|
||||
return;
|
||||
|
||||
case '<':
|
||||
NextChar ();
|
||||
if (C == '=') {
|
||||
|
@ -106,6 +106,8 @@ enum Token {
|
||||
TOK_RPAREN, /* ) */
|
||||
TOK_LBRACK, /* [ */
|
||||
TOK_RBRACK, /* ] */
|
||||
TOK_LCURLY, /* { */
|
||||
TOK_RCURLY, /* } */
|
||||
|
||||
TOK_OVERRIDE_ZP, /* z: */
|
||||
TOK_OVERRIDE_ABS, /* a: */
|
||||
|
Loading…
Reference in New Issue
Block a user