/* 'cmdLine' contains one or several arguments. Each argument can be: - escaped, in which case it starts with '"', ends with '"' and each '"' that is part of the name is escaped with '\\' - unescaped, in which case it start with != '"' and ends with ' ' or '\0' */ void ParseCmdLine(const WCHAR *cmdLine, WStrVec& out) { while (cmdLine) { while (str::IsWs(*cmdLine)) cmdLine++; if ('"' == *cmdLine) cmdLine = ParseQuoted(cmdLine, &out); else if ('\0' != *cmdLine) cmdLine = ParseUnquoted(cmdLine, &out); else cmdLine = NULL; } }
/* ================ Lexer::ReadToken ================ */ const Token *Lexer::ReadToken( void ) { if ( tokPos == -1 ) tokPos = 0; else if ( tokIsUnread ) { tokIsUnread = false; return &token; } while ( bufPos < bufSize ) { // Single line comments if ( !lineComment.IsEmpty() && String::CmpPrefix((const char *)(buffer+bufPos), lineComment.c_str()) == 0 ) { if ( !(flags & LEXER_FULL_LINES) && tokPos > 0 ) { FinishToken(); return &token; } bufPos += 2; if ( tokPos > 0 ) { SkipRestOfLine(); return &token; } SkipRestOfLine(); continue; } // Multiline comments else if ( !blockComment[0].IsEmpty() && String::CmpPrefix((const char *)(buffer+bufPos), blockComment[0].c_str()) == 0 ) { if ( !(flags & LEXER_FULL_LINES) && tokPos > 0 ) { FinishToken(); return &token; } bufPos += 2; int l = line; SkipToCommentEnd(); // If changed line during comment, finish the line. if ( (flags & LEXER_FULL_LINES) && l != line && tokPos > 0 ) { FinishToken(); return &token; } continue; } switch( buffer[bufPos] ) { // Ignore whitespaces case ' ': case '\t': SkipWhiteSpaces(); if ( flags & LEXER_FULL_LINES ) AddToToken( ' ' ); else if ( tokPos > 0 ) { FinishToken(); return &token; } continue; // Newlines case '\n': case '\r': if ( !tokPos ) { FinishLine(); continue; } FinishLine(); return &token; // Quoted tokens case '\"': case '\'': if ( flags & LEXER_FULL_LINES ) { ParseQuoted(); continue; } if ( tokPos > 0 ) { FinishToken(); return &token; } ParseQuoted(); return &token; default: // Check for single char tokens if ( (flags & LEXER_FULL_LINES) == 0 && !singleTokenChars.IsEmpty() ) { char c = buffer[bufPos]; const char *chars = singleTokenChars.c_str(); int num = singleTokenChars.Length(); for( int i=0; i<num; i++ ) { if ( c != chars[i] ) continue; if ( tokPos == 0 ) { AddToToken( buffer[bufPos] ); bufPos++; } FinishToken(); return &token; } } // Add this char to the token AddToToken( buffer[bufPos] ); bufPos++; continue; } } if ( tokPos > 0 ) { FinishToken(); return &token; } line = 0; return NULL; }
/* Parse the next expression */ VyParseTree* Parse(){ /* Check that we have not reached the end of the input stream; if so, return null */ if(!MoreTokensExist()){ return NULL; } /* Get the next token */ VyToken* next = GetNextToken(); /* It's type is used to determine how to continue parsing */ int tokType = next->type; /* Store the result of parsing before returning it */ VyParseTree* expr; /* If it starts with a parenthesis, parse it as a list */ if(tokType == OPAREN){ expr = ParseList(); } /* If it begins with a quote, then parse whatever is next and quote it */ else if(tokType == QUOTE){ expr = ParseQuoted(); } /* Parse a substitution */ else if(tokType == DOLLAR){ expr = ParseSubstitution(); } /* Parse a splicing substitution */ else if(tokType == DOLLARAT){ expr = ParseSpliceSubstitution(); } /* Parse a bracketed list */ else if(tokType == OBRACKET){ expr = ParseBracketedList(); } /* Parse an infix list (curly braces) */ else if(tokType == OCURLY){ expr = ParseCurlyList(); } /* If it is a number, identifier, or string then make a parse tree out of the token */ else if(tokType == IDENT){ VyParseTree* ident = MakeIdent(); SetStrData(ident, next->data); expr = ident; } else if(tokType == NUM){ expr = ParseNumberFromToken(next); } else if(tokType == STRING){ VyParseTree* str = MakeString(); SetStrData(str,next->data); expr = str; } /* Unexpected end of list */ else if(tokType == CPAREN || tokType == CBRACKET || tokType == CCURLY){ VyParseTree* err = ParseError("Unexpected end of list"); SetPosition(err, next->pos); return err; } /* If there is no expression before a :, then the token type will be COLON * Instead of dying, add an error */ else if(tokType == COLON){ VyParseTree* error = ParseError("Reference lacking instance"); SetPosition(error, next->pos); return error; } /* Handle object references: Check whether the next token is a colon. * If so, then use the previously parsed expression (expr) and another * expression gotten from Parse() to create a reference node */ VyToken* lookAhead = GetNextToken(); if(lookAhead != NULL /* Make sure that the token list didn't end before looking at the type */ && lookAhead->type == COLON){ VyParseTree* obj = expr; VyParseTree* ref = Parse(); /* Check for validity */ if(ref == NULL){ expr = Reference(obj, ParseError("Incomplete reference.")); }else{ expr = Reference(obj, ref); } } else{ /* Backtrack one token to make up for the lookahead */ if(lookAhead != NULL) BacktrackToken(); } /* Set the position of the current expression */ SetPosition(expr, next->pos); /* If the tree is an object reference, set the position of * the first part (obj), because it wasn't gotten through a full Parse() call*/ if(expr->type == TREE_REF){ SetPosition(GetObj(expr), next->pos); } return expr; }