From fdb685b8740f465bfbbea0bdee3165ca737e3bda Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 9 May 2004 19:45:07 +0000 Subject: [PATCH] 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 --- src/ca65/expr.c | 38 +++++++++++++++++---- src/ca65/macro.c | 84 +++++++++++++++++++++++++++++++++++----------- src/ca65/nexttok.c | 41 +++++++++++++--------- src/ca65/scanner.c | 10 ++++++ src/ca65/scanner.h | 2 ++ 5 files changed, 132 insertions(+), 43 deletions(-) diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 75e1aee26..e3a1f6c0a 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -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; diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 282bbe687..aea87253c 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -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 (); diff --git a/src/ca65/nexttok.c b/src/ca65/nexttok.c index 4d6e89683..4c89bc1a7 100644 --- a/src/ca65/nexttok.c +++ b/src/ca65/nexttok.c @@ -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 (); } diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 62f7277b2..981b43a68 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -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 == '=') { diff --git a/src/ca65/scanner.h b/src/ca65/scanner.h index b9d38895f..aa5cf6c7f 100644 --- a/src/ca65/scanner.h +++ b/src/ca65/scanner.h @@ -106,6 +106,8 @@ enum Token { TOK_RPAREN, /* ) */ TOK_LBRACK, /* [ */ TOK_RBRACK, /* ] */ + TOK_LCURLY, /* { */ + TOK_RCURLY, /* } */ TOK_OVERRIDE_ZP, /* z: */ TOK_OVERRIDE_ABS, /* a: */ -- 2.39.5