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:
cuz
2004-05-09 19:45:07 +00:00
parent df07cf1114
commit fdb685b874
5 changed files with 132 additions and 43 deletions

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2003 Ullrich von Bassewitz */ /* (C) 1998-2004 Ullrich von Bassewitz */
/* R<>merstra<72>e 52 */ /* R<>merstra<72>e 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -418,15 +418,22 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
/* Handle the .MATCH and .XMATCH builtin functions */ /* Handle the .MATCH and .XMATCH builtin functions */
{ {
int Result; int Result;
enum Token Term;
TokNode* Root = 0; TokNode* Root = 0;
TokNode* Last = 0; TokNode* Last = 0;
TokNode* Node; TokNode* Node;
/* A list of tokens follows. Read this list and remember it building a /* A list of tokens follows. Read this list and remember it building a
* single linked list of tokens including attributes. The list is * 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 */ /* We may not end-of-line of end-of-file here */
if (TokIsSep (Tok)) { if (TokIsSep (Tok)) {
@@ -449,15 +456,27 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
NextTok (); NextTok ();
} }
/* Skip the comma */ /* Skip the terminator token*/
NextTok (); NextTok ();
/* Read the second list which is terminated by the right parenthesis and /* If the token list was enclosed in curly braces, we expect a comma */
* compare each token against the one in the first list. 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; Result = 1;
Node = Root; Node = Root;
while (Tok != TOK_RPAREN) { while (Tok != Term) {
/* We may not end-of-line of end-of-file here */ /* We may not end-of-line of end-of-file here */
if (TokIsSep (Tok)) { if (TokIsSep (Tok)) {
@@ -485,6 +504,11 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
NextTok (); 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 */ /* Check if there are remaining tokens in the first list */
if (Node != 0) { if (Node != 0) {
Result = 0; Result = 0;

View File

@@ -655,7 +655,9 @@ MacEnd:
static void StartExpClassic (Macro* M) static void StartExpClassic (Macro* M)
/* Start expanding the classic macro M */ /* Start expanding the classic macro M */
{ {
MacExp* E; MacExp* E;
enum Token Term;
/* Skip the macro name */ /* Skip the macro name */
NextTok (); NextTok ();
@@ -670,21 +672,29 @@ static void StartExpClassic (Macro* M)
/* Check for maximum parameter count */ /* Check for maximum parameter count */
if (E->ParamCount >= M->ParamCount) { if (E->ParamCount >= M->ParamCount) {
Error ("Too many macro parameters"); ErrorSkip ("Too many macro parameters");
SkipUntilSep ();
break; 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; Last = 0;
while (Tok != TOK_COMMA && Tok != TOK_SEP) { while (Tok != Term && Tok != TOK_SEP) {
TokNode* T; TokNode* T;
/* Check for end of file */ /* Check for end of file */
if (Tok == TOK_EOF) { if (Tok == TOK_EOF) {
Error ("Unexpected end of file"); Error ("Unexpected end of file");
return; FreeMacExp (E);
return;
} }
/* Get the next token in a node */ /* Get the next token in a node */
@@ -694,7 +704,7 @@ static void StartExpClassic (Macro* M)
if (Last == 0) { if (Last == 0) {
E->Params [E->ParamCount] = T; E->Params [E->ParamCount] = T;
} else { } else {
Last->Next = T; Last->Next = T;
} }
Last = T; Last = T;
@@ -705,14 +715,28 @@ static void StartExpClassic (Macro* M)
/* One parameter more */ /* One parameter more */
++E->ParamCount; ++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 */ /* Check for a comma */
if (Tok == TOK_COMMA) { if (Tok == TOK_COMMA) {
NextTok (); NextTok ();
} else { } else {
break; break;
} }
} }
/* We must be at end of line now, otherwise something is wrong */
ExpectSep ();
/* Insert a new token input function */ /* Insert a new token input function */
PushInput (MacExpand, E, ".MACRO"); PushInput (MacExpand, E, ".MACRO");
} }
@@ -736,14 +760,23 @@ static void StartExpDefine (Macro* M)
/* Read the actual parameters */ /* Read the actual parameters */
while (Count--) { 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 */ /* Check if there is really a parameter */
if (TokIsSep (Tok) || Tok == TOK_COMMA) { if (TokIsSep (Tok) || Tok == Term) {
Error ("Macro parameter expected"); ErrorSkip ("Macro parameter #%u is empty", E->ParamCount+1);
SkipUntilSep (); FreeMacExp (E);
return; return;
} }
/* Read tokens for one parameter */ /* Read tokens for one parameter */
Last = 0; Last = 0;
@@ -765,11 +798,22 @@ static void StartExpDefine (Macro* M)
/* And skip it... */ /* And skip it... */
NextTok (); NextTok ();
} while (Tok != TOK_COMMA && !TokIsSep (Tok)); } while (Tok != Term && !TokIsSep (Tok));
/* One parameter more */ /* One parameter more */
++E->ParamCount; ++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 */ /* Check for a comma */
if (Count > 0) { if (Count > 0) {
if (Tok == TOK_COMMA) { if (Tok == TOK_COMMA) {
@@ -782,7 +826,7 @@ static void StartExpDefine (Macro* M)
/* Macro expansion will overwrite the current token. This is a problem /* Macro expansion will overwrite the current token. This is a problem
* for define style macros since these are called from the scanner level. * 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. * expansion is done.
*/ */
E->Final = NewTokNode (); E->Final = NewTokNode ();

View File

@@ -65,18 +65,29 @@ static unsigned RawMode = 0; /* Raw token mode flag/counter */
static TokList* CollectTokens (unsigned Start, unsigned Count) static TokList* CollectTokens (unsigned Start, unsigned Count)
/* Read a list of tokens that is terminated by a right paren. For all tokens /* Read a list of tokens that is optionally enclosed in curly braces and
* starting at the one with index Start, and ending at (Start+Count-1), place * terminated by a right paren. For all tokens starting at the one with index
* them into a token list, and return this token list. * 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 */ /* Create the token list */
TokList* List = NewTokList (); 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 */ /* Read the token list */
unsigned Current = 0; Current = 0;
unsigned Parens = 0; while (Tok != Term) {
while (Parens != 0 || Tok != TOK_RPAREN) {
/* Check for end of line or end of input */ /* Check for end of line or end of input */
if (TokIsSep (Tok)) { if (TokIsSep (Tok)) {
@@ -90,20 +101,18 @@ static TokList* CollectTokens (unsigned Start, unsigned Count)
AddCurTok (List); AddCurTok (List);
} }
/* Check for and count parenthesii */
if (Tok == TOK_LPAREN) {
++Parens;
} else if (Tok == TOK_RPAREN) {
--Parens;
}
/* Get the next token */ /* Get the next token */
++Current; ++Current;
NextTok (); NextTok ();
} }
/* Eat the closing paren */ /* Eat the terminator token */
ConsumeRParen (); 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 the list of collected tokens */
return List; return List;
@@ -422,7 +431,7 @@ void ConsumeSep (void)
/* We expect a separator token */ /* We expect a separator token */
ExpectSep (); ExpectSep ();
/* If we have one, skip it */ /* If we are at end of line, skip it */
if (Tok == TOK_SEP) { if (Tok == TOK_SEP) {
NextTok (); NextTok ();
} }

View File

@@ -980,6 +980,16 @@ CharAgain:
Tok = TOK_RBRACK; Tok = TOK_RBRACK;
return; return;
case '{':
NextChar ();
Tok = TOK_LCURLY;
return;
case '}':
NextChar ();
Tok = TOK_RCURLY;
return;
case '<': case '<':
NextChar (); NextChar ();
if (C == '=') { if (C == '=') {

View File

@@ -106,6 +106,8 @@ enum Token {
TOK_RPAREN, /* ) */ TOK_RPAREN, /* ) */
TOK_LBRACK, /* [ */ TOK_LBRACK, /* [ */
TOK_RBRACK, /* ] */ TOK_RBRACK, /* ] */
TOK_LCURLY, /* { */
TOK_RCURLY, /* } */
TOK_OVERRIDE_ZP, /* z: */ TOK_OVERRIDE_ZP, /* z: */
TOK_OVERRIDE_ABS, /* a: */ TOK_OVERRIDE_ABS, /* a: */