int lexer_read_expandable_recursive(struct lexer_book *bk, char end_marker) { int count = 0; lexer_discard_white_space(bk); while(!bk->eof) { int c = lexer_next_peek(bk); if(c == '$') { count++; lexer_push_token(bk, lexer_read_substitution(bk)); } if(c == '\'') { lexer_read_literal(bk); lexer_push_token(bk, lexer_pack_token(bk, LITERAL)); } else if(c == end_marker) { lexer_next_char(bk); /* Jump end_marker */ return count; } else if(c == '"') count += lexer_read_expandable_recursive(bk, '"'); else if(c == '#' && end_marker != '"') { lexer_discard_comments(bk); return count; } else { count++; lexer_push_token(bk, lexer_read_literal_in_expandable_until(bk, end_marker)); } } /* Found eof before end_marker */ abort(); }
struct token *lexer_read_expandable(struct lexer_book *bk, char end_marker) { struct token *start = lexer_pack_token(bk, LEXPANDABLE); lexer_push_token(bk, start); lexer_read_expandable_recursive(bk, end_marker); lexer_push_token(bk, lexer_pack_token(bk, REXPANDABLE)); return start; }
struct token *lexer_read_expandable(struct lexer *lx, char end_marker) { struct list *tokens = lexer_read_expandable_recursive(lx, end_marker, 0); struct token *t = lexer_concat_expandable(lx, tokens); list_delete(tokens); return t; }
//opened tracks whether it is the opening (opened = 0) or closing (opened = 1) double quote we encounter. struct list *lexer_read_expandable_recursive(struct lexer *lx, char end_marker, int opened) { lexer_discard_white_space(lx); struct list *tokens = list_create(); while(!lx->eof) { int c = lexer_next_peek(lx); if(c == '$') { list_push_tail(tokens, lexer_read_substitution(lx)); } if(c == '\'') { lexer_read_literal(lx); list_push_tail(tokens, lexer_pack_token(lx, TOKEN_LITERAL)); } else if(c == '"' && opened == 0) { lexer_add_to_lexeme(lx, lexer_next_char(lx)); list_push_tail(tokens, lexer_pack_token(lx, TOKEN_LITERAL)); // Add first " tokens = list_splice(tokens, lexer_read_expandable_recursive(lx, '"', 1)); lexer_add_to_lexeme(lx, '"'); list_push_tail(tokens, lexer_pack_token(lx, TOKEN_LITERAL)); // Add closing " if(end_marker == '"') return tokens; } else if(c == '#' && end_marker != '"') { lexer_discard_comments(lx); } else if(c == end_marker) { lexer_next_char(lx); /* Jump end_marker */ return tokens; } else { list_push_tail(tokens, lexer_read_literal_in_expandable_until(lx, end_marker)); } } lexer_report_error(lx, "Found EOF before end marker: %c.\n", end_marker); return NULL; }