1 /* 2 * Copyright 2008, Haiku. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Michael Pfeiffer <laplace@users.sourceforge.net> 7 */ 8 9 #include "AutoDelete.h" 10 #include "CharacterClasses.h" 11 #include "Parser.h" 12 Parser(const char * file)13Parser::Parser(const char* file) 14 : fScanner(file) 15 { 16 if (InitCheck() == B_OK) { 17 NextChar(); 18 } 19 } 20 InitCheck()21status_t Parser::InitCheck() 22 { 23 return fScanner.InitCheck(); 24 } 25 SkipWhitespaces()26void Parser::SkipWhitespaces() 27 { 28 while (IsWhitespace(GetCurrentChar())) { 29 NextChar(); 30 } 31 } 32 SkipComment()33void Parser::SkipComment() 34 { 35 while (GetCurrentChar() != kEof && GetCurrentChar() != kCr) { 36 NextChar(); 37 } 38 NextChar(); 39 } 40 SkipWhitespaceSeparator()41void Parser::SkipWhitespaceSeparator() 42 { 43 while (IsWhitespaceSeparator(GetCurrentChar())) { 44 NextChar(); 45 } 46 } 47 ParseKeyword(Statement * statement)48bool Parser::ParseKeyword(Statement* statement) 49 { 50 // ["?"] 51 if (GetCurrentChar() == '?') { 52 NextChar(); 53 statement->SetType(Statement::kQuery); 54 } 55 // Keyword 56 BString* keyword = fScanner.ScanIdent(); 57 if (keyword == NULL) { 58 Error("Identifier expected"); 59 return false; 60 } 61 statement->SetKeyword(keyword); 62 return true; 63 } 64 ParseTranslation(Value * value,int separator)65bool Parser::ParseTranslation(Value* value, int separator) 66 { 67 BString* translation = fScanner.ScanTranslationValue(separator); 68 if (translation == NULL) { 69 Error("Out of memory scanning translationn!"); 70 return false; 71 } 72 value->SetTranslation(translation); 73 return true; 74 } 75 ParseOption(Statement * statement)76bool Parser::ParseOption(Statement* statement) 77 { 78 // ["^"] 79 bool isSymbolValue = GetCurrentChar() == '^'; 80 if (isSymbolValue) { 81 NextChar(); 82 } 83 84 // [ ... Option ...] 85 if (IsOptionChar(GetCurrentChar())) { 86 87 BString* option = fScanner.ScanOption(); 88 if (option == NULL) { 89 Error("Out of memory scanning option!"); 90 return false; 91 } 92 Value::Type type; 93 if (isSymbolValue) { 94 type = Value::kSymbolValue; 95 } else { 96 type = Value::kStringValue; 97 } 98 Value* value = new Value(option, type); 99 statement->SetOption(value); 100 101 SkipWhitespaceSeparator(); 102 // ["/" Translation ] 103 if (GetCurrentChar() == '/') { 104 NextChar(); 105 return ParseTranslation(value, ':'); 106 } 107 } else { 108 if (isSymbolValue) { 109 Error("Expected symbol value!"); 110 return false; 111 } 112 } 113 return true; 114 } 115 ParseValue(Statement * statement)116bool Parser::ParseValue(Statement* statement) 117 { 118 if (GetCurrentChar() == '"') { 119 NextChar(); 120 121 // "..." 122 AutoDelete<Value> value(new Value()); 123 124 BString* string; 125 if (statement->GetOption() != NULL) { 126 string = fScanner.ScanInvocationValue(); 127 value.Get()->SetType(Value::kInvocationValue); 128 } else { 129 string = fScanner.ScanQuotedValue(); 130 value.Get()->SetType(Value::kQuotedValue); 131 } 132 133 if (string == NULL) { 134 Error("Expected value"); 135 return false; 136 } 137 138 // " is expected 139 if (GetCurrentChar() != '"') { 140 Error("Expected \" at end of value"); 141 return false; 142 } 143 NextChar(); 144 145 value.Get()->SetValue(string); 146 statement->SetValue(value.Release()); 147 } else if (GetCurrentChar() == '^') { 148 // ^ SymbolValue 149 BString* symbol = fScanner.ScanOption(); 150 if (symbol == NULL) { 151 Error("Symbol expected!"); 152 return false; 153 } 154 Value* value = new Value(symbol, Value::kSymbolValue); 155 statement->SetValue(value); 156 } else { 157 // StringValue 158 BString* stringValue = fScanner.ScanStringValue(); 159 if (stringValue == NULL) { 160 Error("String value expected!"); 161 return false; 162 } 163 164 Value* value = new Value(stringValue, Value::kStringValue); 165 statement->SetValue(value); 166 } 167 if (GetCurrentChar() == '/') { 168 NextChar(); 169 return ParseTranslation(statement->GetValue(), kCr); 170 } 171 return true; 172 } 173 174 UpdateStatementType(Statement * statement)175void Parser::UpdateStatementType(Statement* statement) 176 { 177 if (statement->GetType() != Statement::kUnknown) return; 178 179 BString* keyword = statement->GetKeyword(); 180 Statement::Type type; 181 if (keyword->FindFirst("Default") == 0) { 182 type = Statement::kDefault; 183 keyword->RemoveFirst("Default"); 184 } else if (keyword->FindFirst("Param") == 0) { 185 type = Statement::kParam; 186 keyword->RemoveFirst("Param"); 187 } else { 188 type = Statement::kValue; 189 } 190 statement->SetType(type); 191 } 192 193 // ["?"]Keyword [["^"]Option["/"Translation]] 194 // [":" 195 // ["^"]Value ["/" Translation]. 196 // ] ParseStatement()197Statement* Parser::ParseStatement() 198 { 199 AutoDelete<Statement> statement(new Statement()); 200 201 if (!ParseKeyword(statement.Get())) { 202 return NULL; 203 } 204 SkipWhitespaceSeparator(); 205 206 if (!ParseOption(statement.Get())) { 207 return NULL; 208 } 209 210 SkipWhitespaceSeparator(); 211 // [":" ... ] 212 if (GetCurrentChar() == ':') { 213 NextChar(); 214 SkipWhitespaceSeparator(); 215 if (!ParseValue(statement.Get())) { 216 return NULL; 217 } 218 } 219 SkipWhitespaceSeparator(); 220 if (GetCurrentChar() == kEof || GetCurrentChar() == kLf || GetCurrentChar() == kCr) { 221 UpdateStatementType(statement.Get()); 222 Statement* result = statement.Release(); 223 return result; 224 } else { 225 Error("Newline expected at end of statement"); 226 return NULL; 227 } 228 } 229 Parse()230Statement* Parser::Parse() 231 { 232 while (true) { 233 int ch = GetCurrentChar(); 234 if (ch == -1) { 235 return NULL; 236 } 237 if (IsWhitespace(ch)) { 238 SkipWhitespaces(); 239 } else if (ch == '*') { 240 // begin of comment or statement 241 NextChar(); 242 ch = GetCurrentChar(); 243 if (ch == '%') { 244 SkipComment(); 245 } else { 246 return ParseStatement(); 247 } 248 } else { 249 Error("Expected *"); 250 return NULL; 251 } 252 } 253 } 254 255