accept_t lexer_read_line(struct lexer_book * bk) { char c = lexer_next_peek(bk); int colon, equal; bk->substitution_mode = ROOT; switch (c) { case CHAR_EOF: /* Found end of file */ lexer_next_char(bk); return YES; break; case '#': lexer_discard_comments(bk); return YES; break; case '\t': bk->substitution_mode = COMMAND; return lexer_read_command(bk); break; case ' ': /* Eat whitespace and try again */ lexer_discard_white_space(bk); return lexer_read_line(bk); break; case '\n': /* Ignore empty lines and try again */ lexer_next_char(bk); return lexer_read_line(bk); break; case '@': /* Jump @ */ bk->substitution_mode = SYNTAX; lexer_next_char(bk); return lexer_read_syntax(bk); break; default: /* Either makeflow keyword (e.g. export), a file list, or variable assignment */ lexer_discard_white_space(bk); colon = lexer_unquoted_look_ahead_count(bk, ":"); equal = lexer_unquoted_look_ahead_count(bk, "="); fprintf(stderr, "%d %d %c\n", colon, equal, c); if((colon != -1) && (equal == -1 || colon < equal)) { bk->substitution_mode = FILES; return lexer_read_file_list(bk); } else { bk->substitution_mode = SYNTAX; return lexer_read_syntax(bk); } break; } }
struct token *lexer_next_token(struct lexer_book *bk, struct dag_lookup_set *s) { struct token *head; if(list_size(bk->token_queue) == 0) { if(bk->eof) return NULL; lexer_read_line(bk); return lexer_next_token(bk, s); } head = list_pop_head(bk->token_queue); if(head->type == SUBSTITUTION) { char *substitution = dag_lookup(head->lexeme, s); struct lexer_book *bk_s; if(!substitution) { debug(D_NOTICE, "Variable %s has not yet been defined at line %d.\n", head->lexeme, bk->line_number); return lexer_next_token(bk, s); } bk_s = lexer_init_book(STRING, dag_lookup(head->lexeme, s), bk->line_number, bk->column_number); lexer_append_all_tokens(bk, bk_s); lexer_free_book(bk_s); lexer_free_token(head); head = list_pop_head(bk->token_queue); } return head; }
int lexer_read_line(struct lexer * lx) { char c = lexer_next_peek(lx); int colon, equal; switch (c) { case CHAR_EOF: /* Found end of file */ return lexer_next_char(lx); break; case '#': lexer_discard_comments(lx); return 1; break; case '\t': return lexer_read_command(lx); break; case '\n': /* Ignore empty lines and try again */ lexer_next_char(lx); return lexer_read_line(lx); break; case '@': /* Jump @ */ lexer_next_char(lx); return lexer_read_syntax_or_variable(lx); break; default: /* Either makeflow keyword (e.g. export), a file list, or variable assignment */ lexer_discard_white_space(lx); colon = lexer_unquoted_look_ahead_count(lx, ":"); equal = lexer_unquoted_look_ahead_count(lx, "="); /* If there is a colon and it appears before any existing * equal sign read the line as a file list. */ if((colon != -1) && (equal == -1 || colon < equal)) { lexer_read_file_list(lx); } else if(c == ' ' && equal == -1) { /* A command starting with a space.. for backwards compatibility. */ return lexer_read_command(lx); } else { lexer_read_syntax_or_variable(lx); } return 1; break; } }
struct token *lexer_peek_next_token(struct lexer *lx) { if(list_size(lx->token_queue) == 0) { if(lx->eof) return NULL; lexer_read_line(lx); return lexer_peek_next_token(lx); } struct token *head = list_peek_head(lx->token_queue); return head; }
void lexer_append_all_tokens(struct lexer_book *bk, struct lexer_book *bk_s) { struct token *head_s; bk_s->substitution_mode = bk->substitution_mode; while( !bk_s->eof ) { if(lexer_next_peek(bk_s) == CHAR_EOF) { /* Found end of string while completing command */ bk_s->lexeme_end++; bk_s->eof = 1; } else { switch(bk_s->substitution_mode) { case CHAR_EOF: case COMMAND: head_s = lexer_read_command_argument(bk_s); break; case FILES: head_s = lexer_read_file(bk_s); break; case SYNTAX: lexer_read_expandable(bk_s, CHAR_EOF); head_s = lexer_pack_token(bk_s, LITERAL); break; default: lexer_read_line(bk_s); continue; break; } if(head_s) lexer_push_token(bk_s, head_s); } } while( (head_s = list_pop_tail(bk_s->token_queue)) != NULL ) list_push_head(bk->token_queue, head_s); }