double declaration(bool is_const) //Handle 'name = expression' //Declare a variable called "name" with initial value "expresion" { Token t = ts.get(); if (t.kind != name) error("name expected in declaration"); string var_name = t.name; Token t2 = ts.get(); if (t2.kind != '=') error("= missing in declaration of ",var_name); double d = expression(); switch (is_const) { case true: symtable.declare(var_name, d, true); break; default: if (symtable.is_declared(var_name)) symtable.set(var_name, d); else symtable.declare(var_name, d, false); } return d; }
double primary(){ Token t = ts.get(); switch(t.kind){ case '(': // '(' Expression ')'を処理する { double d = expression(); t = ts.get(); if(t.kind != ')') error("')' expected"); return d; } case number: // 数字を表す return t.value; // 数字の値を返す case name: { Token t2 = ts.get(); if(t2.kind == '='){ // 変数に値を代入 double d = expression(); st.set_value(t.name, d); return d; } else{ ts.putback(t2); return st.get_value(t.name); // 変数の値を返す } } case '-': return -primary(); case '+': return primary(); default: error("primary expected"); } }
Variable::Variable(string id, Expression* expression) { Symbol_table *table = Symbol_table::instance(); m_id = id; m_variable = ""; m_expression = expression; m_type = m_expression->get_type(); Symbol* symbol = table->lookup(m_id); m_symbol = symbol; }
double statement() // Divides definition of variable and expressions { Token t = ts.get(); switch(t.kind) { case let: // User wants to declare the variable return names.define_name(let); case constant: return names.define_name(constant); default: // User wants another operation ts.unget(t); return expression(); } }
Token Lexer::on_identifier() { String str = str_.take(); Symbol* sym = symbols.put_identifier(identifier_tok, str); return Token(loc_, sym); }
int main() { try { sym_table.declare("pi", 3.1415926535, false); sym_table.declare("e", 2.7182818284, false); calculate(); return 0; } catch(exception& e) { cerr << e.what() << endl; return 1; } catch(...) { cerr << "exception\n"; return 2; } return 0; }
Variable::Variable(string id1, string id2) { Symbol_table *table = Symbol_table::instance(); m_id = id1; m_expression = NULL; Symbol* symbol = table->lookup(m_id); m_symbol = symbol; m_variable = id2; Gpl_type type; Status status = (m_symbol->get_game_object_value())->get_member_variable_type(id2, type); if(status == MEMBER_NOT_DECLARED) { Error::error(Error::UNDECLARED_MEMBER, m_id, m_variable); m_type = INT; } else m_type = type; }
double primary() { Token t = ts.get(); switch (t.kind) { case '(': { double d = expression(); t = ts.get(); if (t.kind != ')') error("expected ')'"); return d; } case '{': { double d = expression(); t = ts.get(); if (t.kind != '}') error("expected '}'"); return d; } case number: return t.value; case '-': return - primary(); case '+': return primary(); case name: { Token next = ts.get(); if (next.kind == '=') { double d = expression(); sym_table.set(t.name,d); return d; } else { ts.putback(next); return sym_table.get(t.name); } } default: error("primary expected"); } }
int main() { Symbol mySymbol; Symbol anotherSymbol; Symbol_table myTable; double myDouble[2] = {3.14519,4.4}; stringstream ss; string myString[10]; for (int i = 0; i < 10; ++i) { myString[i] = "My Name is Daniel"; } anotherSymbol.setType(DOUBLE); anotherSymbol.setName("myDouble"); anotherSymbol.setValue(&myDouble); mySymbol.setType(STRING); mySymbol.setName("myString"); mySymbol.setValue(&myString); myTable.add(anotherSymbol); myTable.add(mySymbol); myTable.print(cout); }
// "let"が検出されている前提とする // name = expression を処理する // "name"という名前の変数を初期値"expression"で宣言する double declaration(){ Token t = ts.get(); bool constflag = t.kind == constt ? true : false; t = ts.get(); if(t.kind != name) error("name expected in declaration"); string var_name = t.name; Token t2 = ts.get(); if(t2.kind != '=') error("= missing in declaration of ", var_name); double d = expression(); st.define_name(var_name, d, constflag); return d; }
double primary() // Processes semicolons, numbers and returns variables { Token t = ts.get(); // Get a character switch (t.kind) { case '(': { double d = expression(); // Perform calculations in semicolons t = ts.get(); // Get a ')' closing character if (t.kind != ')') error("')' expected"); // If there wasn't any ')' return an error return d; } case sqrts: // Calculate square root of number or group of numbers { return squareroot(); } case pows: { return pow(); } case '-': // For negative digits return - primary(); // Return negative digit case number: // If Token is a number if(narrow_cast<int>(t.value)) return t.value; // Return the number case name: // If Token is a name of variable { string s = t.name; // Save name of variable t = ts.get(); if (t.kind == assign) names.set_value(s,expression()); // If there is an assignment symbol then update the value of variable else ts.unget(t); return names.get_value(s); // Return the value of the variable } case help: return primary(); default: error("primary expected"); // Return an error if an inappropriate character was provided } }
int main() { try { //Predefined names symtable.declare("pi", 3.1415926535, true); symtable.declare("e", 2.7182818284, true); calculate(); return 0; } catch (exception& e) { cerr << "error: " << e.what() << '\n'; char c; while (cin >> c && c != ';') ; return 1; } catch (...) { cerr << "unknown exception!\n"; char c; while (cin >> c && c != ';') ; return 2; } }
int main() { ostream & os = cout; Symbol_table *table = Symbol_table::instance(); table->add_symbol("a", INT); table->add_symbol("b", INT); table->add_symbol("z", INT); table->add_symbol("d", DOUBLE); table->add_symbol("s", STRING); table->add_symbol("k", INT, 2); table->add_symbol("l", DOUBLE, 3); table->add_symbol("p", STRING, 4); table->print(os); }
double declaration() { Token t = ts.get(); if (t.kind != VAR) { ts.end(); error ("Valid name expected in declaration"); } string name = t.name; Token t2 = ts.get(); if (t2.kind != '=') { ts.end(); error("'=' missing in declaration of " ,name); } double d = expression(); variables.set_value(name, d); return d; }
double declaration(Token k) // Taken from: http://www.stroustrup.com/Programming/Solutions/Ch7/e7-1.cpp // handle: name = expression // declare a variable called "name" with the initial value "expression" // k will be "let" or "con"(stant) { Token t = ts.get(); if (t.kind != name) error ("name expected in declaration"); string var_name = t.name; Token t2 = ts.get(); if (t2.kind != '=') error("= missing in declaration of ", var_name); double d = expression(); sym_table.declare(var_name,d,k.kind==let); return d; }
double primary() { Token t = ts.get(); switch (t.kind) { // Handles expressions in parentheses. case '(': { double d = expression(); t = ts.get(); if (t.kind != ')') { ts.end(); error("')' expected"); } return d; } // This handles unary + or - case '-': return - primary(); case '+': return + primary(); case NUMBER: return t.value; case VAR: return variables.get_value(t.name); case SQRT: { t=ts.get(); if(t.kind!='(') { ts.end(); error("sqrt: sqrt must be of the form sqrt(expression)"); } ts.unget(t); double d = primary(); if(d<0) { ts.end(); error("sqrt: cannot take square root of a negative number"); } return sqrt(d); } default: ts.end(); error("primary expected"); } }
void init_token(Symbol_table& syms, Token_kind k, char const* s) { syms.put_symbol(k, s); spelling.emplace(k, s); }
Token Lexer::on_symbol() { Symbol const* sym = symbols.get(str_.take()); return Token(loc_, sym); }
namespace calc { // -------------------------------------------------------------------------- // // Symbols Symbol_table symbols; // -------------------------------------------------------------------------- // // Tokens char const* get_spelling(Token_kind k) { switch (k) { case error_tok: return "<error>"; case lparen_tok: return "("; case rparen_tok: return ")"; case backslash_tok: return "\\"; case dot_tok: return "."; case equal_tok: return "="; case semicolon_tok: return ";"; case identifier_tok: return "<identifier>"; } lingo_unreachable(); } // -------------------------------------------------------------------------- // // Lexing void Lexer::save() { str_.put(cs_.get()); } // Lexically analyze a single token. Token Lexer::scan() { while (!cs_.eof()) { space(); loc_ = cs_.location(); switch (cs_.peek()) { case '\0': return eof(); case '(': return symbol1(); case ')': return symbol1(); case '\\': return symbol1(); case '.': return symbol1(); case '=': return symbol1(); case ';': return symbol1(); default: // TODO: Unfold into cases. if (is_alpha(cs_.peek())) return identifier(); else error(); } } return {}; } void Lexer::error() { lingo::error(loc_, "unrecognized character '{}'", cs_.get()); } void Lexer::space() { while (is_space(cs_.peek())) cs_.ignore(); } Token Lexer::eof() { return Token{}; } Token Lexer::symbol1() { save(); return on_symbol(); } // letter ::= [a-z][A-Z] void Lexer::letter() { save(); } Token Lexer::identifier() { letter(); while (is_alpha(cs_.peek())) letter(); return on_identifier(); } Token Lexer::on_symbol() { Symbol const* sym = symbols.get(str_.take()); return Token(loc_, sym); } Token Lexer::on_identifier() { String str = str_.take(); Symbol* sym = symbols.put_identifier(identifier_tok, str); return Token(loc_, sym); } void Lexer::operator()() { while (Token tok = scan()) ts_.put(tok); } } // namespace calc
double primary() // deal with numbers, square roots, exponents, parentheses, and brackets { Token t = ts.get(); switch (t.kind) { case root: { t = ts.get(); if (t.kind != '(') error("'(' expected"); double d = expression(); if (d < 0) error ("negative argument for sqrt()"); t = ts.get(); if (t.kind != ')') error ("')' expected"); return sqrt(d); } case exponent: { t = ts.get(); if (t.kind != '(') error("'(' expected"); double d = expression(); t = ts.get(); if (t.kind != ',') error("expected two arguments for pow()"); int exp = narrow_cast<int>(expression()); t = ts.get(); if (t.kind != ')') error("')'expected"); return power(d, exp); } case '{': // handle '{' expression '}' { double d = expression(); t = ts.get(); if (t.kind != '}') error("'}' expected"); return d; } case '(': // handle '(' expression ')' { double d = expression(); t = ts.get(); if (t.kind != ')') error("')' expected"); return d; } case number: // we use '8' to represent a number return t.value; // return the number's value case name: return symtable.get(t.name); case '-': return -primary(); case '+': return primary(); default: error("primary expected"); } }