//========================================================================== // // DoActionSpecials // handles action specials as code pointers // //========================================================================== bool DoActionSpecials(FState & state, bool multistate, int * statecount, Baggage &bag) { int i; const ACSspecials *spec; if ((spec = is_special (sc_String, sc_StringLen)) != NULL) { int paramindex=PrepareStateParameters(&state, 6); StateParameters[paramindex]=spec->Special; // Make this consistent with all other parameter parsing if (SC_CheckToken('(')) { for (i = 0; i < 5;) { StateParameters[paramindex+i+1]=ParseExpression (false, bag.Info->Class); i++; if (!SC_CheckToken (',')) break; } SC_MustGetToken (')'); } else i=0; if (i < spec->MinArgs) { SC_ScriptError ("Too few arguments to %s", spec->name); } if (i > MAX (spec->MinArgs, spec->MaxArgs)) { SC_ScriptError ("Too many arguments to %s", spec->name); } state.Action = A_CallSpecial; return true; } return false; }
Sentencia* Sintactico::ParseAssignmentStatement(string nombre_id) { list<Qualifier*> qualifier_list = ParseQualifiers(); if ( proximo_token.GetTipo() == op_asignacion ) { proximo_token = analizador_lexico->ObtenerSiguienteToken(); Expresion* expr = ParseExpression(); if ( proximo_token.GetTipo() == punt_puntocoma ) proximo_token = analizador_lexico->ObtenerSiguienteToken(); else throw SyntaxException("Falta un punto y coma",analizador_lexico->GetLineaActual()); Identificador* identificador = new Identificador(nombre_id,qualifier_list); return new SentenciaAsignacion(identificador,expr); } else throw SyntaxException("no se encontro el operador de asignacion",analizador_lexico->GetLineaActual()); }
// Parser high-level token void SqlParser::Parse(Token *token, int scope, int *result_sets) { bool exists = false; // If application scope is set, start from an application statement if(_source_app != 0) { _level = LEVEL_APP; if(_source_app == APP_COBOL && _cobol != NULL) exists = _cobol->ParseStatement(token); _level = LEVEL_SQL; } if(exists == true) return; if(ParseStatement(token, scope, result_sets) == true) return; if(ParseSystemProcedure(NULL, token) == true) return; exists = ParseExpression(token); // Standalone function call if(exists == true && token->type == TOKEN_FUNCTION && token->t_type != TOKEN_STATEMENT && scope == SQL_SCOPE_PROC) { // Netezza requires explicit CALL keyword if(_target == SQL_NETEZZA) { Prepend(token, "CALL ", L"CALL ", 5); } } }
TExpressionPtr ExpressionParser::ParseParameterizedVariableExpression(StringPtrLen str) const { BracketsContent content; auto name = content.Parse(str); if (str.Len() == name.Len()) { return TExpressionPtr(); } name.Trim(); CheckQualifier(name, "Variable name"); auto variable = m_variable_mgr.FindVariable(name); if (nullptr == variable) { Error("Usage of undefined variable '", name, "'."); } TExpressionPtrVector actual_params; actual_params.reserve(5); StringPtrLen param; while (content.GetPart(param)) { auto param_expr = ParseExpression(param); actual_params.push_back(std::move(param_expr)); } if (actual_params.size() != variable->GetParameterCount()) { Error("Incorrect amount of parameters during usage of variable '", variable->GetName(), "'. Expected amount - ", variable->GetParameterCount(), ", actual amount - ", actual_params.size(), "."); } return variable->GetExpression()->CloneWithSubstitution(actual_params); }
nsresult nsAbQueryStringToExpression::Convert ( const nsACString &aQueryString, nsIAbBooleanExpression** expression) { nsresult rv; nsCAutoString q(aQueryString); q.StripWhitespace(); const char *queryChars = q.get(); nsCOMPtr<nsISupports> s; rv = ParseExpression(&queryChars, getter_AddRefs(s)); NS_ENSURE_SUCCESS(rv, rv); // Case: Not end of string if (*queryChars != 0) return NS_ERROR_FAILURE; nsCOMPtr<nsIAbBooleanExpression> e(do_QueryInterface(s, &rv)); NS_ENSURE_SUCCESS(rv, rv); NS_IF_ADDREF(*expression = e); return rv; }
void CFormulaParser::ParseDebugTab(CString function_text) { p_debug_tab->Clear(); CString next_line; int separator_index = 0; // Split lines while (AfxExtractSubString(next_line, function_text, separator_index, '\n')) { ++separator_index; int pos = next_line.Find('='); if (pos < 0) { // No equality-sign found. Empty line or not valid continue; } // Expression-text: everything behind first "=" int expresion_length = next_line.GetLength() - pos - 1; CString expression_text = next_line.Right(expresion_length); // Parse this line _tokenizer.SetInput(expression_text); TPParseTreeNode expression = ParseExpression(); // Care about operator precendence _parse_tree_rotator.Rotate(expression, &expression); // Add line and expression to debug-tab p_debug_tab->AddExpression(expression_text, expression); } }
/** * postfix-expression: * primary-expression * postfix-expression [ expression ] * postfix-expression ( [argument-expression-list] ) * postfix-expression . identifier * postfix-expression -> identifier * postfix-expression ++ * postfix-expression -- */ static AstExpression ParsePostfixExpression(void) { AstExpression expr, p; expr = ParsePrimaryExpression(); while (1) { switch (CurrentToken) { case TK_LBRACKET: CREATE_AST_NODE(p, Expression); p->op = OP_INDEX; p->kids[0] = expr; NEXT_TOKEN; p->kids[1] = ParseExpression(); Expect(TK_RBRACKET); expr = p; break; case TK_LPAREN: CREATE_AST_NODE(p, Expression); p->op = OP_CALL; p->kids[0] = expr; NEXT_TOKEN; if (CurrentToken != TK_RPAREN) { AstNode *tail; /// function call expression's second kid is actually /// a list of expression instead of a single expression p->kids[1] = ParseAssignmentExpression(); tail = &p->kids[1]->next; while (CurrentToken == TK_COMMA) { NEXT_TOKEN; *tail = (AstNode)ParseAssignmentExpression(); tail = &(*tail)->next; } } Expect(TK_RPAREN); expr = p; break; case TK_DOT: case TK_POINTER: CREATE_AST_NODE(p, Expression); p->op = (CurrentToken == TK_DOT ? OP_MEMBER : OP_PTR_MEMBER); p->kids[0] = expr; NEXT_TOKEN; if (CurrentToken != TK_ID) { Error(&p->coord, "Expect identifier as struct or union member"); } else { p->val = TokenValue; NEXT_TOKEN; } expr = p; break; case TK_INC: case TK_DEC: CREATE_AST_NODE(p, Expression); p->op = (CurrentToken == TK_INC) ? OP_POSTINC : OP_POSTDEC; p->kids[0] = expr; NEXT_TOKEN; expr = p; break; default: return expr; } } }
static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defaults, Baggage &bag) { static TArray<FPropParam> params; static TArray<FString> strings; params.Clear(); strings.Clear(); params.Reserve(1); params[0].i = 0; if (prop->params[0] != '0') { const char * p = prop->params; bool nocomma; bool optcomma; while (*p) { FPropParam conv; FPropParam pref; nocomma = false; conv.s = NULL; pref.s = NULL; pref.i = -1; bag.ScriptPosition = sc; switch ((*p) & 223) { case 'X': // Expression in parentheses or number. { FxExpression *x = NULL; if (sc.CheckString ("(")) { x = new FxDamageValue(new FxIntCast(ParseExpression(sc, bag.Info)), true); sc.MustGetStringName(")"); } else { sc.MustGetNumber(); if (sc.Number != 0) { x = new FxDamageValue(new FxConstant(sc.Number, bag.ScriptPosition), false); } } conv.exp = x; params.Push(conv); } break; case 'I': sc.MustGetNumber(); conv.i = sc.Number; break; case 'F': sc.MustGetFloat(); conv.d = sc.Float; break; case 'Z': // an optional string. Does not allow any numerical value. if (sc.CheckFloat()) { nocomma = true; sc.UnGet(); break; } // fall through case 'S': sc.MustGetString(); conv.s = strings[strings.Reserve(1)] = sc.String; break; case 'T': sc.MustGetString(); conv.s = strings[strings.Reserve(1)] = strbin1(sc.String); break; case 'C': if (sc.CheckNumber ()) { int R, G, B; R = clamp (sc.Number, 0, 255); sc.CheckString (","); sc.MustGetNumber (); G = clamp (sc.Number, 0, 255); sc.CheckString (","); sc.MustGetNumber (); B = clamp (sc.Number, 0, 255); conv.i = MAKERGB(R, G, B); pref.i = 0; } else { sc.MustGetString (); conv.s = strings[strings.Reserve(1)] = sc.String; pref.i = 1; } break; case 'M': // special case. An expression-aware parser will not need this. conv.i = ParseMorphStyle(sc); break; case 'N': // special case. An expression-aware parser will not need this. conv.i = ParseThingActivation(sc); break; case 'L': // Either a number or a list of strings if (sc.CheckNumber()) { pref.i = 0; conv.i = sc.Number; } else { pref.i = 1; params.Push(pref); params[0].i++; do { sc.MustGetString (); conv.s = strings[strings.Reserve(1)] = sc.String; params.Push(conv); params[0].i++; } while (sc.CheckString(",")); goto endofparm; } break; default: assert(false); break; } if (pref.i != -1) { params.Push(pref); params[0].i++; } params.Push(conv); params[0].i++; endofparm: p++; // Hack for some properties that have to allow comma less // parameter lists for compatibility. if ((optcomma = (*p == '_'))) p++; if (nocomma) { continue; } else if (*p == 0) { break; } else if (*p >= 'a') { if (!sc.CheckString(",")) { if (optcomma) { if (!sc.CheckFloat()) break; else sc.UnGet(); } else break; } } else { if (!optcomma) sc.MustGetStringName(","); else sc.CheckString(","); } } } // call the handler try { prop->Handler(defaults, bag.Info, bag, ¶ms[0]); } catch (CRecoverableError &error) { sc.ScriptError("%s", error.GetMessage()); } return true; }
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant) { FxExpression *x = NULL; int v; if (type == TypeSound) { sc.MustGetString(); x = new FxConstant(FSoundID(sc.String), sc); } else if (type == TypeBool || type == TypeSInt32 || type == TypeFloat64) { x = ParseExpression (sc, cls, constant); if (constant && !x->isConstant()) { sc.ScriptMessage("Default parameter must be constant."); FScriptPosition::ErrorCounter++; } // Do automatic coercion between bools, ints and floats. if (type == TypeBool) { x = new FxBoolCast(x); } else if (type == TypeSInt32) { x = new FxIntCast(x); } else { x = new FxFloatCast(x); } } else if (type == TypeName || type == TypeString) { sc.SetEscape(true); sc.MustGetString(); sc.SetEscape(false); if (type == TypeName) { x = new FxConstant(sc.String[0] ? FName(sc.String) : NAME_None, sc); } else { x = new FxConstant(strbin1(sc.String), sc); } } else if (type == TypeColor) { sc.MustGetString (); if (sc.Compare("none")) { v = -1; } else if (sc.Compare("")) { v = 0; } else { int c = V_GetColor (NULL, sc.String); // 0 needs to be the default so we have to mark the color. v = MAKEARGB(1, RPART(c), GPART(c), BPART(c)); } ExpVal val; val.Type = TypeColor; val.Int = v; x = new FxConstant(val, sc); } else if (type == TypeState) { // This forces quotation marks around the state name. sc.MustGetToken(TK_StringConst); if (sc.String[0] == 0 || sc.Compare("None")) { x = new FxConstant((FState*)NULL, sc); } else if (sc.Compare("*")) { if (constant) { x = new FxConstant((FState*)(intptr_t)-1, sc); } else sc.ScriptError("Invalid state name '*'"); } else { x = new FxMultiNameState(sc.String, sc); } } else if (type->GetClass() == RUNTIME_CLASS(PClassPointer)) { // Actor name sc.SetEscape(true); sc.MustGetString(); sc.SetEscape(false); x = new FxClassTypeCast(static_cast<PClassPointer *>(type)->ClassRestriction, new FxConstant(FName(sc.String), sc)); } else { assert(false && "Unknown parameter type"); x = NULL; } return x; }
static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cls) { PType *type; int maxelems = 1; // Only non-native classes may have user variables. if (!cls->bRuntimeClass) { sc.ScriptError("Native classes may not have user variables"); } // Read the type and make sure it's acceptable. sc.MustGetAnyToken(); if (sc.TokenType != TK_Int && sc.TokenType != TK_Float) { sc.ScriptMessage("User variables must be of type 'int' or 'float'"); FScriptPosition::ErrorCounter++; } type = sc.TokenType == TK_Int ? (PType *)TypeSInt32 : (PType *)TypeFloat64; sc.MustGetToken(TK_Identifier); // For now, restrict user variables to those that begin with "user_" to guarantee // no clashes with internal member variable names. if (sc.StringLen < 6 || strnicmp("user_", sc.String, 5) != 0) { sc.ScriptMessage("User variable names must begin with \"user_\""); FScriptPosition::ErrorCounter++; } FName symname = sc.String; // We must ensure that we do not define duplicates, even when they come from a parent table. if (symt->FindSymbol(symname, true) != NULL) { sc.ScriptMessage ("'%s' is already defined in '%s' or one of its ancestors.", symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global"); FScriptPosition::ErrorCounter++; return; } if (sc.CheckToken('[')) { FxExpression *expr = ParseExpression(sc, cls, true); if (!expr->isConstant()) { sc.ScriptMessage("Array size must be a constant"); FScriptPosition::ErrorCounter++; maxelems = 1; } else { maxelems = static_cast<FxConstant *>(expr)->GetValue().GetInt(); } sc.MustGetToken(']'); if (maxelems <= 0) { sc.ScriptMessage("Array size must be positive"); FScriptPosition::ErrorCounter++; maxelems = 1; } type = NewArray(type, maxelems); } sc.MustGetToken(';'); PField *sym = cls->AddField(symname, type, 0); if (sym == NULL) { sc.ScriptMessage ("'%s' is already defined in '%s'.", symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global"); FScriptPosition::ErrorCounter++; } }
/// ParseDeclarationTypeSpec - Parse a declaration type spec construct. /// /// [R502]: /// declaration-type-spec := /// intrinsic-type-spec /// or TYPE ( derived-type-spec ) /// or CLASS ( derived-type-spec ) /// or CLASS ( * ) bool Parser::ParseDeclarationTypeSpec(DeclSpec &DS, bool AllowSelectors, bool AllowOptionalCommaAfterCharLength) { // [R403]: // intrinsic-type-spec := // INTEGER [ kind-selector ] // or REAL [ kind-selector ] // or DOUBLE PRECISION // or COMPLEX [ kind-selector ] // or DOUBLE COMPLEX // or CHARACTER [ char-selector ] // or BYTE // or LOGICAL [ kind-selector ] switch (Tok.getKind()) { default: DS.SetTypeSpecType(DeclSpec::TST_unspecified); break; case tok::kw_INTEGER: DS.SetTypeSpecType(DeclSpec::TST_integer); break; case tok::kw_REAL: DS.SetTypeSpecType(DeclSpec::TST_real); break; case tok::kw_COMPLEX: DS.SetTypeSpecType(DeclSpec::TST_complex); break; case tok::kw_CHARACTER: DS.SetTypeSpecType(DeclSpec::TST_character); break; case tok::kw_BYTE: DS.SetTypeSpecType(DeclSpec::TST_logical); DS.setByte(); // equivalent to Kind = 1 break; case tok::kw_LOGICAL: DS.SetTypeSpecType(DeclSpec::TST_logical); break; case tok::kw_DOUBLEPRECISION: DS.SetTypeSpecType(DeclSpec::TST_real); DS.setDoublePrecision(); // equivalent to Kind = 8 break; case tok::kw_DOUBLECOMPLEX: DS.SetTypeSpecType(DeclSpec::TST_complex); DS.setDoublePrecision(); // equivalent to Kind = 8 break; } if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) if (ParseTypeOrClassDeclTypeSpec(DS)) return true; ExprResult Kind; ExprResult Len; // FIXME: no Kind for double complex, double precision and byte switch (DS.getTypeSpecType()) { case DeclSpec::TST_struct: break; default: ConsumeToken(); if (ConsumeIfPresent(tok::star)) { // FIXME: proper obsolete COMPLEX*16 support ConsumeAnyToken(); DS.setDoublePrecision(); } if (!AllowSelectors) break; if (ConsumeIfPresent(tok::l_paren)) { Kind = ParseSelector(true); if (Kind.isInvalid()) return true; if(!ExpectAndConsume(tok::r_paren, 0, "", tok::r_paren)) return true; } break; case DeclSpec::TST_character: // [R424]: // char-selector := // length-selector // or ( LEN = type-param-value , KIND = scalar-int-initialization-expr ) // or ( type-param-value , # // # [ KIND = ] scalar-int-initialization-expr ) // or ( KIND = scalar-int-initialization-expr [, LEN = type-param-value]) // // [R425]: // length-selector := // ( [ LEN = ] type-param-value ) // or * char-length [,] // // [R426]: // char-length := // ( type-param-value ) // or scalar-int-literal-constant // // [R402]: // type-param-value := // scalar-int-expr // or * // or : ConsumeToken(); if(ConsumeIfPresent(tok::star)) { ParseCharacterStarLengthSpec(DS); if(AllowOptionalCommaAfterCharLength) ConsumeIfPresent(tok::comma); } else { if (!AllowSelectors) break; if(ConsumeIfPresent(tok::l_paren)) { if(IsPresent(tok::kw_LEN)) { Len = ParseSelector(false); if (Len.isInvalid()) return true; } else if(IsPresent(tok::kw_KIND)) { Kind = ParseSelector(true); if (Kind.isInvalid()) return true; } else { Len = ParseExpectedFollowupExpression("("); if(Len.isInvalid()) return true; } if(ConsumeIfPresent(tok::comma)) { // FIXME: if (Tok.is(tok::kw_LEN)) { if (Len.isInvalid()) return Diag.ReportError(Tok.getLocation(), "multiple LEN selectors for this type"); Len = ParseSelector(false); if (Len.isInvalid()) return true; } else if (Tok.is(tok::kw_KIND)) { if (Kind.isInvalid()) return Diag.ReportError(Tok.getLocation(), "multiple KIND selectors for this type"); Kind = ParseSelector(true); if (Kind.isInvalid()) return true; } else { if (Kind.isInvalid()) return Diag.ReportError(Tok.getLocation(), "multiple KIND selectors for this type"); ExprResult KindExpr = ParseExpression(); Kind = KindExpr; } } if(!ExpectAndConsume(tok::r_paren)) return true; } } break; } // Set the selectors for declspec. if(Kind.isUsable()) DS.setKindSelector(Kind.get()); if(Len.isUsable()) DS.setLengthSelector(Len.get()); return false; }
PRIVATE void ParseStatement( void ) { Accept( IDENTIFIER ); Accept( ASSIGNMENT ); /* ":=" has token name ASSIGNMENT. */ ParseExpression(); }
struct Expression* ParseAtom(const RegexpTokenType* token_stream, int* pos) { int origpos = *pos; char c = token_stream[*pos]; if(IS_LITERAL_TOKEN(c)) { /* Atom := string of literal characters/ANY_CHAR/LINE_START/LINE_END */ struct LiteralStringExpression* result = malloc(sizeof(struct LiteralStringExpression)); int num_tokens; result->base.typecode = LITERAL_STRING_EXPRESSION_TYPE; result->base.group_number = NO_GROUP; for( ; token_stream[*pos] != 0; (*pos)++) { if (!IS_LITERAL_TOKEN(token_stream[*pos])) { break; } } num_tokens = (*pos) - origpos; result->literal_string = malloc((num_tokens + 1) * sizeof(RegexpTokenType)); result->literal_string[num_tokens] = 0; /* null terminate */ memmove(result->literal_string, &token_stream[origpos], num_tokens*sizeof(RegexpTokenType)); return (struct Expression*)result; } switch (c) { case SPECIAL_SET_PREFIX: { /* Atom := SPECIAL_SET_PREFIX <letter>, just invoke its regexp */ (*pos)++; if (predefined_char_classes[token_stream[*pos]].token_string != NULL) { int pre_pos = 0; struct Expression* result = ParseExpression(predefined_char_classes[token_stream[*pos]].token_string, &pre_pos); (*pos)++; return result; } switch(token_stream[*pos]) { case 'B': /* Between \w and \w OR between \W and \W */ case 'b': { /* Between \w and \W OR between \W and \w */ int temp_pos = 0; struct ZeroWidthExpression* left = malloc(sizeof(struct ZeroWidthExpression)); struct ZeroWidthExpression* right = malloc(sizeof(struct ZeroWidthExpression)); struct UnionExpression* result = malloc(sizeof(struct UnionExpression)); left->base.typecode = ZERO_WIDTH_EXPRESSION_TYPE; left->base.group_number = NO_GROUP; temp_pos=0; ParseSet(predefined_char_classes['w'].token_string, &temp_pos, left->preceding_set); if (token_stream[*pos] == 'b') { temp_pos=0; ParseSet(predefined_char_classes['W'].token_string, &temp_pos, left->following_set); } else { temp_pos=0; ParseSet(predefined_char_classes['w'].token_string, &temp_pos, left->following_set); } right->base.typecode = ZERO_WIDTH_EXPRESSION_TYPE; right->base.group_number = NO_GROUP; temp_pos=0; ParseSet(predefined_char_classes['W'].token_string, &temp_pos, right->preceding_set); if (token_stream[*pos] == 'b') { temp_pos=0; ParseSet(predefined_char_classes['w'].token_string, &temp_pos, right->following_set); } else { temp_pos=0; ParseSet(predefined_char_classes['W'].token_string, &temp_pos, right->following_set); } result->base.typecode = UNION_EXPRESSION_TYPE; result->base.group_number = NO_GROUP; result->left_expression = (struct Expression*)left; result->right_expression = (struct Expression*)right; (*pos)++; return (struct Expression*)result; } } goto parse_error; } case ANY_CHAR: { struct CharSetExpression* result = malloc(sizeof(struct CharSetExpression)); result->base.typecode = CHARSET_EXPRESSION_TYPE; result->base.group_number = NO_GROUP; SetAllCharSet(result->set); (*pos)++; return (struct Expression*)result; } case LINE_START: { struct ZeroWidthExpression* result = malloc(sizeof(struct ZeroWidthExpression)); result->base.typecode = ZERO_WIDTH_EXPRESSION_TYPE; result->base.group_number = NO_GROUP; ZeroOutCharSet(result->preceding_set); BitArrayInsert(result->preceding_set, BEFORE_STRING_CHAR); SetAllCharSet(result->following_set); (*pos)++; return (struct Expression*)result; } case LINE_END: { struct ZeroWidthExpression* result = malloc(sizeof(struct ZeroWidthExpression)); result->base.typecode = ZERO_WIDTH_EXPRESSION_TYPE; result->base.group_number = NO_GROUP; SetAllCharSet(result->preceding_set); ZeroOutCharSet(result->following_set); BitArrayInsert(result->following_set, AFTER_STRING_CHAR); (*pos)++; return (struct Expression*)result; } case SET_OPEN: { /* Atom := character set */ struct CharSetExpression* result = malloc(sizeof(struct CharSetExpression)); result->base.typecode = CHARSET_EXPRESSION_TYPE; result->base.group_number = NO_GROUP; if (ParseSet(token_stream, pos, result->set) == 0) { destroy_expression((struct Expression*)result); goto parse_error; } return (struct Expression*)result; } case GROUP_OPEN: { /* Atom := GROUP_OPEN Expression GROUP_CLOSE */ int open_pos = *pos; int group_num = 0; struct Expression* expr = ((*pos)++, ParseExpression(token_stream, pos)); int i; if (expr == NULL || token_stream[*pos] != GROUP_CLOSE) { destroy_expression(expr); goto parse_error; } /* Find group number by counting preceding (s */ for(i=0; i<open_pos; i++) { if (token_stream[i] == GROUP_OPEN) { group_num++; } } expr->group_number = group_num; (*pos)++; return expr; } default: /* Unexpected char, parse error */ goto parse_error; } parse_error: *pos = origpos; return NULL; }
/** * primary-expression: * ID * constant * string-literal * ( expression ) */ static AstExpression ParsePrimaryExpression(void) { AstExpression expr; switch (CurrentToken) { case TK_ID: CREATE_AST_NODE(expr, Expression); expr->op = OP_ID; expr->val = TokenValue; NEXT_TOKEN; return expr; /// Notice: Only when parsing constant and string literal, /// ty member in astExpression is used since from OP_CONST /// and OP_STR alone the expression's type can't be determined case TK_INTCONST: case TK_UINTCONST: case TK_LONGCONST: case TK_ULONGCONST: case TK_LLONGCONST: case TK_ULLONGCONST: case TK_FLOATCONST: case TK_DOUBLECONST: case TK_LDOUBLECONST: CREATE_AST_NODE(expr, Expression); if (CurrentToken >= TK_FLOATCONST) CurrentToken++; /// nasty, requires that both from TK_INTCONST to TK_LDOUBLECONST /// and from INT to LDOUBLE are consecutive expr->ty = T(INT + CurrentToken - TK_INTCONST); expr->op = OP_CONST; expr->val = TokenValue; NEXT_TOKEN; return expr; case TK_STRING: case TK_WIDESTRING: CREATE_AST_NODE(expr, Expression); expr->ty = ArrayOf(((String)TokenValue.p)->len + 1, CurrentToken == TK_STRING ? T(CHAR) : WCharType); expr->op = OP_STR; expr->val = TokenValue; NEXT_TOKEN; return expr; case TK_LPAREN: NEXT_TOKEN; expr = ParseExpression(); Expect(TK_RPAREN); return expr; default: Error(&TokenCoord, "Expect identifier, string, constant or ("); return Constant0; } }
static FProduction *ParseExpression (FCommandLine &argv, int &parsept) { if (parsept >= argv.argc()) return NULL; const char *token = argv[parsept++]; FProduction *prod1 = NULL, *prod2 = NULL, *prod3 = NULL; if (IsFloat (token)) { return NewDoubleProd (atof(token)); } else if (stricmp (token, "true") == 0) { return NewDoubleProd (1.0); } else if (stricmp (token, "false") == 0) { return NewDoubleProd (0.0); } else { for (size_t i = 0; i < countof(Producers); ++i) { if (strcmp (Producers[i].Token, token) == 0) { prod1 = ParseExpression (argv, parsept); prod2 = ParseExpression (argv, parsept); if (prod1 == NULL || prod2 == NULL) { goto missing; } if (Producers[i].StringProducer == NULL) { DoubleCoerce (prod1, prod2); } else if (Producers[i].DoubleProducer == NULL) { MustStringCoerce (prod1, prod2); } else { MaybeStringCoerce (prod1, prod2); } if (prod1->Type == PROD_String) { prod3 = Producers[i].StringProducer ((FStringProd *)prod1, (FStringProd *)prod2); } else { prod3 = Producers[i].DoubleProducer ((FDoubleProd *)prod1, (FDoubleProd *)prod2); } goto done; } } if (strcmp ("!", token) == 0) { prod1 = ParseExpression (argv, parsept); if (prod1 == NULL) { goto missing; } if (prod1->Type == PROD_String) { prod1 = StringToDouble (prod1); } prod3 = NewDoubleProd (!static_cast<FDoubleProd *>(prod1)->Value); goto done; } return NewStringProd (token); } missing: Printf ("Missing argument to %s\n", token); done: if (prod2 != NULL) M_Free (prod2); if (prod1 != NULL) M_Free (prod1); return prod3; }
FxExpression *ParseParameter(FScanner &sc, PClass *cls, char type, bool constant) { FxExpression *x = NULL; int v; switch(type) { case 'S': case 's': // Sound name sc.MustGetString(); x = new FxConstant(FSoundID(sc.String), sc); break; case 'M': case 'm': // Actor name sc.SetEscape(true); sc.MustGetString(); sc.SetEscape(false); x = new FxClassTypeCast(RUNTIME_CLASS(AActor), new FxConstant(FName(sc.String), sc)); break; case 'T': case 't': // String sc.SetEscape(true); sc.MustGetString(); sc.SetEscape(false); x = new FxConstant(sc.String[0]? FName(sc.String) : NAME_None, sc); break; case 'C': case 'c': // Color sc.MustGetString (); if (sc.Compare("none")) { v = -1; } else if (sc.Compare("")) { v = 0; } else { int c = V_GetColor (NULL, sc.String); // 0 needs to be the default so we have to mark the color. v = MAKEARGB(1, RPART(c), GPART(c), BPART(c)); } { ExpVal val; val.Type = VAL_Color; val.Int = v; x = new FxConstant(val, sc); break; } case 'L': case 'l': { // This forces quotation marks around the state name. sc.MustGetToken(TK_StringConst); if (sc.String[0] == 0 || sc.Compare("None")) { x = new FxConstant((FState*)NULL, sc); } else if (sc.Compare("*")) { if (constant) { x = new FxConstant((FState*)(intptr_t)-1, sc); } else sc.ScriptError("Invalid state name '*'"); } else { x = new FxMultiNameState(sc.String, sc); } break; } case 'X': case 'x': case 'Y': case 'y': x = ParseExpression (sc, cls); if (constant && !x->isConstant()) { sc.ScriptMessage("Default parameter must be constant."); FScriptPosition::ErrorCounter++; } break; default: assert(false); return NULL; } return x; }
static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClass *cls) { FExpressionType valuetype; // Only non-native classes may have user variables. if (!cls->bRuntimeClass) { sc.ScriptError("Native classes may not have user variables"); } // Read the type and make sure it's int. sc.MustGetAnyToken(); if (sc.TokenType != TK_Int) { sc.ScriptMessage("User variables must be of type int"); FScriptPosition::ErrorCounter++; } valuetype = VAL_Int; sc.MustGetToken(TK_Identifier); // For now, restrict user variables to those that begin with "user_" to guarantee // no clashes with internal member variable names. if (sc.StringLen < 6 || strnicmp("user_", sc.String, 5) != 0) { sc.ScriptMessage("User variable names must begin with \"user_\""); FScriptPosition::ErrorCounter++; } FName symname = sc.String; if (sc.CheckToken('[')) { FxExpression *expr = ParseExpression(sc, cls); int maxelems = expr->EvalExpression(NULL).GetInt(); delete expr; sc.MustGetToken(']'); if (maxelems <= 0) { sc.ScriptMessage("Array size must be positive"); FScriptPosition::ErrorCounter++; maxelems = 1; } valuetype.MakeArray(maxelems); } sc.MustGetToken(';'); // We must ensure that we do not define duplicates, even when they come from a parent table. if (symt->FindSymbol(symname, true) != NULL) { sc.ScriptMessage ("'%s' is already defined in '%s' or one of its ancestors.", symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global"); FScriptPosition::ErrorCounter++; return; } PSymbolVariable *sym = new PSymbolVariable(symname); sym->offset = cls->Extend(sizeof(int) * (valuetype.Type == VAL_Array ? valuetype.size : 1)); sym->ValueType = valuetype; sym->bUserVar = true; if (symt->AddSymbol(sym) == NULL) { delete sym; sc.ScriptMessage ("'%s' is already defined in '%s'.", symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global"); FScriptPosition::ErrorCounter++; } }
static void ParseNativeVariable (FScanner &sc, PSymbolTable * symt, PClass *cls) { FExpressionType valuetype; if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0) { sc.ScriptMessage ("variables can only be imported by internal class and actor definitions!"); FScriptPosition::ErrorCounter++; } // Read the type and make sure it's int or float. sc.MustGetAnyToken(); switch (sc.TokenType) { case TK_Int: valuetype = VAL_Int; break; case TK_Float: valuetype = VAL_Float; break; case TK_Angle_t: valuetype = VAL_Angle; break; case TK_Fixed_t: valuetype = VAL_Fixed; break; case TK_Bool: valuetype = VAL_Bool; break; case TK_Identifier: valuetype = VAL_Object; // Todo: Object type sc.ScriptError("Object type variables not implemented yet!"); break; default: sc.ScriptError("Invalid variable type %s", sc.String); return; } sc.MustGetToken(TK_Identifier); FName symname = sc.String; if (sc.CheckToken('[')) { FxExpression *expr = ParseExpression (sc, cls); int maxelems = expr->EvalExpression(NULL).GetInt(); delete expr; sc.MustGetToken(']'); valuetype.MakeArray(maxelems); } sc.MustGetToken(';'); const FVariableInfo *vi = FindVariable(symname, cls); if (vi == NULL) { sc.ScriptError("Unknown native variable '%s'", symname.GetChars()); } PSymbolVariable *sym = new PSymbolVariable(symname); sym->offset = vi->address; // todo sym->ValueType = valuetype; sym->bUserVar = false; if (symt->AddSymbol (sym) == NULL) { delete sym; sc.ScriptMessage ("'%s' is already defined in '%s'.", symname.GetChars(), cls? cls->TypeName.GetChars() : "Global"); FScriptPosition::ErrorCounter++; } }
double CalculateExpression(const std::string& i_string, size_t& o_errorPos) { std::vector<ExpressionItem*> items; size_t maxNestingLevel = 0; size_t parseResult = ParseExpression(i_string, items, maxNestingLevel); if (parseResult != kDefaultErrorPos) { o_errorPos = parseResult; return 0.0; } size_t validateResult = ValidateExpression(items); if (validateResult != kDefaultErrorPos) { o_errorPos = validateResult; return 0.0; } size_t nestingLevel = maxNestingLevel + 1; while (true) { nestingLevel--; size_t loc = 0; while (loc < items.size()) { while (loc < items.size() && (items[loc]->NestingLevel() != nestingLevel)) { loc++; } if (loc >= items.size()) { break; } size_t startLoc = loc; while (loc < items.size() && (items[loc]->NestingLevel() == nestingLevel)) { loc++; } size_t endLoc = loc; if (startLoc != endLoc) { double value = CalculateSequence(items, startLoc, endLoc); for (size_t i = startLoc; i < endLoc; ++i) { delete items[i]; } items.erase(items.begin() + startLoc, items.begin() + (endLoc - 1)); Operand* operand = new Operand(value, nestingLevel - 1, 0); items[startLoc] = operand; } } if (nestingLevel == 0) { break; } } assert(items.size() == 1); Operand* operand = dynamic_cast<Operand*>(items[0]); double result = operand->GetValue(); delete operand; return result; }
// Atom ::= "(" Expression ")" | "[" [^] Range "]" | Characters Instruction* ParseAtom(const char **ppc, ParseInfo &info) { Instruction *i = 0; const char *pc = *ppc; switch (*pc) { case '(': { Group::TriState dnl = Group::Inherit; Group::TriState nc = Group::Inherit; Group::TriState ml = Group::Inherit; bool capture = true; bool consume = true; bool invert = false; bool reverse = false; std::string name = ""; ++pc; if (*pc == '?') { ++pc; if (*pc == '#') { // skip everything until ) and from behave as if ParseAtom was // called starting next character ++pc; while (*pc != ')') { if (*pc == '\0') { return 0; } ++pc; } *ppc = ++pc; return ParseAtom(ppc, info); } if (*pc == ':') { capture = false; ++pc; } else if (*pc == '(') { // conditional ++pc; std::string cond; while (*pc != ')') { if (*pc == '\0') { return 0; } cond.push_back(*pc); ++pc; } ++pc; Instruction *ci = ParseExpression(&pc, info); if (!ci || *pc != ')') { if (ci) { delete ci; } return 0; } ++pc; Alternative *alt = dynamic_cast<Alternative*>(ci); Instruction *ifTrue, *ifFalse; if (alt == 0) { ifTrue = ci; ifFalse = 0; } else { ifTrue = alt->first()->clone(); ifFalse = alt->second()->clone(); delete alt; } *ppc = pc; int index = 0; if (sscanf(cond.c_str(), "%d", &index) != 1) { return new Conditional(cond, ifTrue, ifFalse); } else { return new Conditional(index, ifTrue, ifFalse); } } else if (*pc == 'P') { ++pc; if (*pc == '<') { ++pc; while (*pc != '>') { if (*pc == '\0') { return 0; } name.push_back(*pc); ++pc; } ++pc; } else if (*pc == '=') { std::string name; ++pc; while (*pc != ')') { if (*pc == '\0') { return 0; } name.push_back(*pc); ++pc; } ++pc; *ppc = pc; return new Backsubst(name); } else { return 0; } } else if (*pc == '=') { // positive lookahead capture = false; consume = false; ++pc; } else if (*pc == '!') { // negative lookahead capture = false; consume = false; invert = true; ++pc; } else if (*pc == '<') { ++pc; if (*pc == '=') { // positive lookbehind capture = false; consume = false; reverse = true; ++pc; } else if (*pc == '!') { // negative lookbehind capture = false; consume = false; reverse = true; invert = true; ++pc; } else { Log::PrintError("[gcore] rex/ParseAtom: Invalid group format"); return 0; } } else if (*pc == 'i' || *pc == 'm' || *pc == 's' || *pc == '-') { //capture = false; //consume = false; if (*pc == 'i') { // case sensitive off nc = Group::On; ++pc; } if (*pc == 'm') { // multiline on (. matches \r\n) ml = Group::On; ++pc; } if (*pc == 's') { // dot matches new line on dnl = Group::On; ++pc; } if (*pc == '-') { ++pc; if (*pc == 'i') { // case sensitive on nc = Group::Off; ++pc; } if (*pc == 'm') { // multiline off ml = Group::Off; ++pc; } if (*pc == 's') { // dot matches newline off dnl = Group::Off; ++pc; } } if (*pc != ':' && *pc != ')') { // either followed by : or group end (meaning we just want to change exp exec flags) Log::PrintError("[gcore] rex/ParseAtom: Invalid group format"); return 0; } if (*pc == ':') { ++pc; // would having a closing parent here be problematic } else { capture = false; consume = false; } } } int gidx = (capture ? (++(info.numGroups)) : -1); unsigned short flags = (unsigned short)(reverse ? Rex::Reverse : 0); if (*pc != ')') { i = ParseExpression(&pc, info); } if (*pc != ')') { if (i) { delete i; } return 0; } #ifdef _DEBUG_REX Log::PrintDebug("[gcore] rex/ParseAtom: Create group"); Log::SetIndentLevel(Log::GetIndentLevel()+1); Log::PrintDebug("index: %d", gidx); Log::PrintDebug("invert: %d", invert); Log::PrintDebug("consume: %d", consume); Log::PrintDebug("flags: %d", flags); Log::PrintDebug("nc: %d", nc); Log::PrintDebug("ml: %d", ml); Log::PrintDebug("dnl: %d", dnl); Log::PrintDebug("name: %d", name.c_str()); Log::PrintDebug("code: "); if (i) { std::ostringstream oss; Log::SetIndentLevel(Log::GetIndentLevel()+1) i->toStream(oss); Log::PrintDebug(oss.str().c_str()); Log::SetIndentLevel(Log::GetIndentLevel()-1) } Log::SetIndentLevel(Log::GetIndentLevel()-1); #endif i = new Group(gidx, i, !consume, invert, flags, nc, ml, dnl, name); #ifdef _DEBUG_REX Log::PrintDebug("[gcore] rex/ParseAtom: Group created"); #endif ++pc; break; } case '[': { bool inv = false; ++pc; if (*pc == '^') { inv = true; ++pc; } i = ParseRange(&pc, inv, info); if (!i) { return 0; } if (*pc != ']') { Log::PrintError("[gcore] rex/ParseAtom: Invalid character '%c' in expression, expected ']'", *pc); if (i) { delete i; } return 0; } ++pc; break; } default: i = ParseCharacters(&pc, info); if (!i) { i = ParseZerowidth(&pc, info); if (!i) { return 0; } } } *ppc = pc; return i; }
// ParsePrimaryExpr - Parse a primary expression. // // [R701]: // primary := // constant // or designator // or array-constructor // or structure-constructor // or function-reference // or type-param-inquiry // or type-param-name // or ( expr ) Parser::ExprResult Parser::ParsePrimaryExpr(bool IsLvalue) { ExprResult E; SourceLocation Loc = Tok.getLocation(); // FIXME: Add rest of the primary expressions. switch (Tok.getKind()) { default: if (isTokenIdentifier()) goto possible_keyword_as_ident; Diag.Report(getExpectedLoc(), diag::err_expected_expression); return ExprError(); case tok::error: Lex(); return ExprError(); case tok::l_paren: { ConsumeParen(); E = ParseExpression(); // complex constant. if(ConsumeIfPresent(tok::comma)) { if(E.isInvalid()) return E; auto ImPart = ParseExpectedFollowupExpression(","); if(ImPart.isInvalid()) return ImPart; E = Actions.ActOnComplexConstantExpr(Context, Loc, getMaxLocationOfCurrentToken(), E, ImPart); } ExpectAndConsume(tok::r_paren, 0, "", tok::r_paren); break; } case tok::l_parenslash : { return ParseArrayConstructor(); break; } case tok::logical_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = LogicalConstantExpr::Create(Context, getTokenRange(), StrPair.first, Context.LogicalTy); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::binary_boz_constant: case tok::octal_boz_constant: case tok::hex_boz_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = BOZConstantExpr::Create(Context, Loc, getMaxLocationOfCurrentToken(), StrPair.first); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::char_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); E = CharacterConstantExpr::Create(Context, getTokenRange(), StringRef(NumStr), Context.CharacterTy); ConsumeToken(); // Possible substring if(IsPresent(tok::l_paren)) return ParseSubstring(E); break; } case tok::int_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = IntegerConstantExpr::Create(Context, getTokenRange(), StrPair.first); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); Lex(); break; } case tok::real_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = RealConstantExpr::Create(Context, getTokenRange(), NumStr, Context.RealTy); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::double_precision_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); // Replace the d/D exponent into e exponent for(size_t I = 0, Len = NumStr.length(); I < Len; ++I) { if(NumStr[I] == 'd' || NumStr[I] == 'D') { NumStr[I] = 'e'; break; } else if(NumStr[I] == '_') break; } StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = RealConstantExpr::Create(Context, getTokenRange(), NumStr, Context.DoublePrecisionTy); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::identifier: possible_keyword_as_ident: E = Parser::ParseDesignator(IsLvalue); if (E.isInvalid()) return E; break; case tok::minus: Lex(); E = Parser::ParsePrimaryExpr(); if (E.isInvalid()) return E; E = Actions.ActOnUnaryExpr(Context, Loc, UnaryExpr::Minus, E); break; case tok::plus: Lex(); E = Parser::ParsePrimaryExpr(); if (E.isInvalid()) return E; E = Actions.ActOnUnaryExpr(Context, Loc, UnaryExpr::Plus, E); break; } return E; }
int FAO::Compute() { ExprAST * tree = ParseExpression(); return tree->GetValue(); }
const char* RegExp::ParseFactor(StrPP& factor) { StrPP tmp; factor = ""; switch(reExpression[0]) { case LPAREN: // ( - parenthesised expression reExpression++; ParseExpression(tmp); factor += tmp; if(reExpression != RPAREN) return(NULL); reExpression++; break; case CCL: // [ - character class; Ex: [0-9] reExpression++; ParseCCL(tmp); factor += tmp; if(reExpression != CCLEND) return(NULL); reExpression++; break; case ANY: // . case EOL: // $ factor += reExpression[0]; reExpression++; break; case ESCAPE : // \ reExpression++; factor += LITCHAR; factor += ParseEscape(); reExpression++; break; case CLOSURE: // * case POS_CLO: // + case ZERO_ONE: // ? case NEGATE: // ^ case CCLEND: // ] case RPAREN: // ) case OR: // | return(NULL); // not valid characters default: // literal character factor += LITCHAR; factor += reExpression[0]; reExpression++; break; } if(reExpression == CLOSURE || // check for closure reExpression == ZERO_ONE || reExpression == POS_CLO) { if(ParseClosure(factor) == _RE_FALSE_) return(NULL); } return factor; }
/* returnexpr * */ static shared_ptr<ExprAST> ParseReturnExpr() { getNextToken();//eat return return shared_ptr<ExprAST>(new ReturnAST(ParseExpression())); }
TExpressionPtr ExpressionParser::ParseOperationExpression(StringPtrLen str) const { BracketsBalancer balancer; auto max_operation = OperationType::None; auto max_operation_amount = -1L; auto tail = str; // Find operation with zero bracket balance and with maximum value. // Maximum value means minimal arithmetic priority. for (; tail.Len() > 0; tail.RemoveLeft(1)) { if (!balancer.ProcessChar(tail.At(0)) && balancer.GetBalance() == 0) { OperationType operation = StartsWithOperation(tail); // TODO: Skip the whole operation symbols if (operation != OperationType::None) { if (operation > max_operation) { max_operation = operation; max_operation_amount = 1; } else if (operation == max_operation) { ++max_operation_amount; } } } } if (OperationType::None == max_operation) { // No operations with zero balance return TExpressionPtr(); } assert(balancer.GetBalance() == 0); auto max_operation_str = OperationTypeToString(max_operation); auto max_operation_str_len = std::strlen(max_operation_str); if (OperationType::Negation == max_operation) { if (!str.StartsWith(max_operation_str)) { Error("Incorrect usage of unary operation '", max_operation_str, "'."); } str.RemoveLeft(max_operation_str_len); auto child_expression = ParseExpression(str); return std::make_unique<OperationExpression>(std::move(child_expression)); } TExpressionPtrVector children_expressions; children_expressions.reserve(max_operation_amount + 1); tail = str; while (tail.Len() > 0) { if (!balancer.ProcessChar(tail.At(0)) && balancer.GetBalance() == 0) { if (tail.StartsWith(max_operation_str)) { auto child_expression = ParseExpression(str.Left(tail.Ptr())); children_expressions.push_back(std::move(child_expression)); tail.RemoveLeft(max_operation_str_len); str = tail; continue; } } tail.RemoveLeft(1); } auto child_expression = ParseExpression(str); children_expressions.push_back(std::move(child_expression)); return std::make_unique<OperationExpression>(max_operation, std::move(children_expressions)); }
void TParser::ParseCASE(void) { TCaseItem *pCaseItemList; // ptr to list of CASE items int caseBranchFlag; // true if another CASE branch, // else false pCaseItemList = NULL; //--Append placeholders for the location of the token that //--follows the CASE statement and of the CASE branch table. //--Remember the locations of these placeholders. int atFollowLocationMarker = PutLocationMarker(); int atBranchTableLocationMarker = PutLocationMarker(); //--<expr> GetTokenAppend(); TType *pExprType = ParseExpression()->Base(); //--Verify the type of the CASE expression. if ( (pExprType != pIntegerType) && (pExprType != pCharType) && (pExprType->form != fcEnum)) { Error(errIncompatibleTypes); } //--OF Resync(tlOF, tlCaseLabelStart); CondGetTokenAppend(tcOF, errMissingOF); //--Loop to parse CASE branches. caseBranchFlag = TokenIn(token, tlCaseLabelStart); while (caseBranchFlag) { if (TokenIn(token, tlCaseLabelStart)) { ParseCaseBranch(pExprType, pCaseItemList); } if (token == tcSemicolon) { GetTokenAppend(); caseBranchFlag = true; } else if (TokenIn(token, tlCaseLabelStart)) { Error(errMissingSemicolon); caseBranchFlag = true; } else caseBranchFlag = false; } //--Append the branch table to the intermediate code. FixupLocationMarker(atBranchTableLocationMarker); TCaseItem *pItem = pCaseItemList; TCaseItem *pNext; do { PutCaseItem(pItem->labelValue, pItem->atBranchStmt); pNext = pItem->next; delete pItem; pItem = pNext; } while (pItem); PutCaseItem(0, 0); // end of table //--END Resync(tlEND, tlStatementStart); CondGetTokenAppend(tcEND, errMissingEND); FixupLocationMarker(atFollowLocationMarker); }
/* ===================================================== * Write down the code needed to call COMPARATOR(...) * ===================================================== */ void CallComponent(PARSER_CONFIG* conf, CSV_INPUT *data, FILE *flp, int nLn) { int i = 0; int ret = 0; int nIO = 0; EXPRESSION expr; bool foundComp = false; int nInp = 0, nOut = 0; COMPONENT comp; fprintf(stderr, " MakeComponentCall: \n"); fprintf(stderr, " MakeComponentCall: nom_row = %d\n", data->nom_row); fprintf(stderr, " MakeComponentCall: Id_compon = %d\n", data->Id_compon); fprintf(stderr, " MakeComponentCall: page_alg = %s\n", data->page_alg); fprintf(stderr, " MakeComponentCall: Type_compon = %s\n", data->Type_compon); fprintf(stderr, " MakeComponentCall: run_compon = %s\n", data->run_compon); fprintf(stderr, " MakeComponentCall: data_struct = %s\n", data->data_struct); fprintf(stderr, " MakeComponentCall: description = %s\n", data->description); fprintf(stderr, " MakeComponentCall: comments = %s\n", data->comments); fprintf(stderr, "\n"); fprintf(stderr, "nComp = %d\n", conf->nComp); // Fill component name and data structure name // We're going through preconfigured components one by one, // checking radiy's native names against the one given on CSV-data for (int i = 0; i < conf->nComp; i++) { fprintf(stderr, "%d: %s <-> %s\n", i, data->run_compon, conf->comp[i].radiyName); // "It's a kind of magic"(c) - we found what we need // Now let's fill local COMPONENT buffer with component's info // from configuration structure so we can use it for writing the code if (!strcmp(data->run_compon, conf->comp[i].radiyName)) { memcpy((char*)&comp, (char*)&(conf->comp[i]), sizeof(COMPONENT)); foundComp = true; conf->comp[i].nFound++; // increment number of found components break; } } if (!foundComp) { // Put a note into cscan code fprintf(flp, "\n\n/* Warning: component type %s mentioned in line %d not found in configuration*/\n\n", data->run_compon, data->nom_row); // And drop the same line into a log or onto a screen fprintf(stderr, "\n\n/* Warning: component type %s mentioned in line %d not found in configuration*/\n\n", data->run_compon, data->nom_row); // Sorry, done return; } // Put cleanup statement in front of component call fprintf(flp, "\tmemset(&%s, \'\\x0\', sizeof(%s));\n\n", comp.datastructName, comp.datatypeName); // Loop through all arguments, expressions are expected ////////////////////////////////////////////////////// // This is output loop ////////////////////////////////////////////////////// i = 0; while (strlen(data->args[i])) { fprintf(stderr, "MakeComponentCall: args[%d] = %s\n", i, data->args[i]); ret = ParseExpression(data->args[i], &expr); fprintf(stderr, "\nInput loop EXPRESSION: ret = %d\n", ret); fprintf(stderr, "signal = %d\n", expr.signal); fprintf(stderr, "number = %d\n", expr.number); fprintf(stderr, "list = %d\n", expr.list); fprintf(stderr, "error = %d\n", expr.error); fprintf(stderr, "lp = %s\n", expr.lp); fprintf(stderr, "rp = %s\n", expr.rp); fprintf(stderr, "mddname = %s\n", expr.mddname); fprintf(stderr, "inMDD = %d\\nn", expr.inMDD); if (ret == IAM_EXPRESSION) { //fprintf(flp, "/* Original: %s*/ \n", data->args[i]); // Here we make two loops through comp's IO array - the 1st one in serch of inputs, // the 2nd one in search of outputs // Get all inputs 1st nIO = 0; while (strlen(comp.inputNames[nIO])) { if (!strcmp(comp.inputNames[nIO], expr.lp)) { if (expr.signal) // mdd name appears on the right { if (expr.rp[0] == '!') GetSignalInfo(nLn, expr.rp + 1, expr.mddname); // function will update nSig and fill *(signals + nSig) else GetSignalInfo(nLn, expr.rp, expr.mddname); // function will update nSig and fill *(signals + nSig) if ((signals + nSig - 1)->found) fprintf(flp, "\t// Internal ID: %s External ID: %s\n", (signals + nSig - 1)->radiyname, (signals + nSig - 1)->extID); /* fprintf(flp, "\t// Coordinates: %s\n", (signals + nSig - 1)->coord); fprintf(flp, "\t// Descrption: %s\n", (signals + nSig - 1)->descr); }*/ if (expr.Not) // all that inputIsArray staff is a f*****g patch - force RADIY to get rid of that shit!! { //if ((comp.inputIsArray) && (!strcmp(comp.inputNames[nIO], "XIN"))) // PATCH!!!! if (comp.inputIsArray[nIO]) fprintf(flp, "\t%s.%s[0] = !%s;\t// PATCH %s\n", comp.datastructName, expr.lp, expr.mddname, comp.inputDesc[nIO]); else fprintf(flp, "\t%s.%s = !%s;\t// %s\n", comp.datastructName, expr.lp, expr.mddname, comp.inputDesc[nIO]); } else { //if ((comp.inputIsArray) && (!strcmp(comp.inputNames[nIO], "XIN"))) // PATCH!!!! if (comp.inputIsArray[nIO]) fprintf(flp, "\t%s.%s[0] = %s;\t// PATCH %s\n", comp.datastructName, expr.lp, expr.mddname, comp.inputDesc[nIO]); else fprintf(flp, "\t%s.%s = %s;\t// %s\n", comp.datastructName, expr.lp, expr.mddname, comp.inputDesc[nIO]); } strcpy(data->inputs[nInp], expr.rp ); nInp++; } else if (expr.number) // right part appears on the right as is { fprintf(flp, "\t%s.%s = %s;\t// %s\n", comp.datastructName, expr.lp, expr.rp, comp.inputDesc[nIO]); strcpy(data->inputs[nInp], expr.rp ); nInp++; } else if (expr.list) // we have a coma-sep list on the right. // Let's parse it and print as lp[n] = ... { fprintf(flp, "\t// %s\n", comp.inputDesc[nIO]); ParseVarList(nLn, flp, comp.datastructName, expr.lp, expr.rp); int nLst = 0; while (strlen(inputsLst[nLst])) { strcpy(data->inputs[nInp], inputsLst[nLst]); nInp++; nLst++; } } } nIO++; } } else fprintf(flp, "/*Not a valid expression: %s*/ \n", data->args[i]); i++; } // Write a component call as all inputs are set fprintf(flp, "\n\t%s(&%s);\n\n", comp.simexecName, comp.datastructName); ////////////////////////////////////////////////////// // This is output loop, exactly the same as the one // for inputs above ////////////////////////////////////////////////////// i = 0; while (strlen(data->args[i])) { ret = ParseExpression(data->args[i], &expr); if (ret == IAM_EXPRESSION) { //fprintf(flp, "/* Original: %s*/ \n", data->args[i]); // Here we make two loops through comp's IO array - the 1st one in serch of inputs, // the 2nd one in search of outputs // Get all outputs now nIO = 0; while (strlen(comp.outputNames[nIO])) { if (!strcmp(comp.outputNames[nIO], expr.lp)) { if (expr.signal) // mdd name appears on the left, that's fine { if (expr.rp[0] == '!') GetSignalInfo(nLn, expr.rp + 1, expr.mddname); // function will update nSig and fill *(signals + nSig) else GetSignalInfo(nLn, expr.rp, expr.mddname); // function will update nSig and fill *(signals + nSig) if ((signals + nSig - 1)->found) fprintf(flp, "\t// Internal ID: %s External ID: %s\n", (signals + nSig - 1)->radiyname, (signals + nSig - 1)->extID); /* fprintf(flp, "\t// Coordinates: %s\n", (signals + nSig - 1)->coord); fprintf(flp, "\t// Descrption: %s\n", (signals + nSig - 1)->descr); */ if (expr.Not) fprintf(flp, "\t%s = !%s.%s;\t//%s\n", expr.mddname, comp.datastructName, expr.lp, comp.outputDesc[nIO]); else fprintf(flp, "\t%s = %s.%s;\t//%s\n", expr.mddname, comp.datastructName, expr.lp, comp.outputDesc[nIO]); strcpy(data->outputs[nOut], expr.rp ); nOut++; } else if (expr.number) // This is error - invalid left part of the equation { fprintf(flp, "\t/* Error, wrong LP: %s = %s.%s;*/ \n", expr.rp, comp.datastructName, expr.lp); strcpy(data->outputs[nOut], expr.rp ); nOut++; } } nIO++; } } else fprintf(flp, "/*Not a valid expression: %s*/ \n", data->args[i]); i++; } fprintf(flp, "\n\n"); return; }
//========================================================================== // // ParseStates // parses a state block // //========================================================================== int ParseStates(FActorInfo * actor, AActor * defaults, Baggage &bag) { FString statestring; intptr_t count = 0; FState state; FState * laststate = NULL; intptr_t lastlabel = -1; int minrequiredstate = -1; SC_MustGetStringName ("{"); SC_SetEscape(false); // disable escape sequences in the state parser while (!SC_CheckString ("}") && !sc_End) { memset(&state,0,sizeof(state)); statestring = ParseStateString(); if (!statestring.CompareNoCase("GOTO")) { do_goto: statestring = ParseStateString(); if (SC_CheckString ("+")) { SC_MustGetNumber (); statestring += '+'; statestring += sc_String; } // copy the text - this must be resolved later! if (laststate != NULL) { // Following a state definition: Modify it. laststate->NextState = (FState*)copystring(statestring); } else if (lastlabel >= 0) { // Following a label: Retarget it. RetargetStates (count+1, statestring); } else { SC_ScriptError("GOTO before first state"); } } else if (!statestring.CompareNoCase("STOP")) { do_stop: if (laststate!=NULL) { laststate->NextState=(FState*)-1; } else if (lastlabel >=0) { RetargetStates (count+1, NULL); } else { SC_ScriptError("STOP before first state"); continue; } } else if (!statestring.CompareNoCase("WAIT") || !statestring.CompareNoCase("FAIL")) { if (!laststate) { SC_ScriptError("%s before first state", sc_String); continue; } laststate->NextState=(FState*)-2; } else if (!statestring.CompareNoCase("LOOP")) { if (!laststate) { SC_ScriptError("LOOP before first state"); continue; } laststate->NextState=(FState*)(lastlabel+1); } else { const char * statestrp; SC_MustGetString(); if (SC_Compare (":")) { laststate = NULL; do { lastlabel = count; AddState(statestring, (FState *) (count+1)); statestring = ParseStateString(); if (!statestring.CompareNoCase("GOTO")) { goto do_goto; } else if (!statestring.CompareNoCase("STOP")) { goto do_stop; } SC_MustGetString (); } while (SC_Compare (":")); // continue; } SC_UnGet (); if (statestring.Len() != 4) { SC_ScriptError ("Sprite names must be exactly 4 characters\n"); } memcpy(state.sprite.name, statestring, 4); state.Misc1=state.Misc2=0; state.ParameterIndex=0; SC_MustGetString(); statestring = (sc_String+1); statestrp = statestring; state.Frame=(*sc_String&223)-'A'; if ((*sc_String&223)<'A' || (*sc_String&223)>']') { SC_ScriptError ("Frames must be A-Z, [, \\, or ]"); state.Frame=0; } SC_MustGetNumber(); sc_Number++; state.Tics=sc_Number&255; state.Misc1=(sc_Number>>8)&255; if (state.Misc1) state.Frame|=SF_BIGTIC; while (SC_GetString() && !sc_Crossed) { if (SC_Compare("BRIGHT")) { state.Frame|=SF_FULLBRIGHT; continue; } if (SC_Compare("OFFSET")) { if (state.Frame&SF_BIGTIC) { SC_ScriptError("You cannot use OFFSET with a state duration larger than 254!"); } // specify a weapon offset SC_MustGetStringName("("); SC_MustGetNumber(); state.Misc1=sc_Number; SC_MustGetStringName (","); SC_MustGetNumber(); state.Misc2=sc_Number; SC_MustGetStringName(")"); continue; } // Make the action name lowercase to satisfy the gperf hashers strlwr (sc_String); int minreq=count; if (DoActionSpecials(state, !statestring.IsEmpty(), &minreq, bag)) { if (minreq>minrequiredstate) minrequiredstate=minreq; goto endofstate; } PSymbol *sym = bag.Info->Class->Symbols.FindSymbol (FName(sc_String, true), true); if (sym != NULL && sym->SymbolType == SYM_ActionFunction) { PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym); state.Action = afd->Function; if (!afd->Arguments.IsEmpty()) { const char *params = afd->Arguments.GetChars(); int numparams = (int)afd->Arguments.Len(); int v; if (!islower(*params)) { SC_MustGetStringName("("); } else { if (!SC_CheckString("(")) goto endofstate; } int paramindex = PrepareStateParameters(&state, numparams); int paramstart = paramindex; bool varargs = params[numparams - 1] == '+'; if (varargs) { StateParameters[paramindex++] = 0; } while (*params) { switch(*params) { case 'I': case 'i': // Integer SC_MustGetNumber(); v=sc_Number; break; case 'F': case 'f': // Fixed point SC_MustGetFloat(); v=fixed_t(sc_Float*FRACUNIT); break; case 'S': case 's': // Sound name SC_MustGetString(); v=S_FindSound(sc_String); break; case 'M': case 'm': // Actor name case 'T': case 't': // String SC_SetEscape(true); SC_MustGetString(); SC_SetEscape(false); v = (int)(sc_String[0] ? FName(sc_String) : NAME_None); break; case 'L': case 'l': // Jump label if (SC_CheckNumber()) { if (strlen(statestring)>0) { SC_ScriptError("You cannot use A_Jump commands with a jump index on multistate definitions\n"); } v=sc_Number; if (v<1) { SC_ScriptError("Negative jump offsets are not allowed"); } { int minreq=count+v; if (minreq>minrequiredstate) minrequiredstate=minreq; } } else { if (JumpParameters.Size()==0) JumpParameters.Push(NAME_None); v = -(int)JumpParameters.Size(); // This forces quotation marks around the state name. SC_MustGetToken(TK_StringConst); FString statestring = sc_String; // ParseStateString(); const PClass *stype=NULL; int scope = statestring.IndexOf("::"); if (scope >= 0) { FName scopename = FName(statestring, scope, false); if (scopename == NAME_Super) { // Super refers to the direct superclass scopename = actor->Class->ParentClass->TypeName; } JumpParameters.Push(scopename); statestring = statestring.Right(statestring.Len()-scope-2); stype = PClass::FindClass (scopename); if (stype == NULL) { SC_ScriptError ("%s is an unknown class.", scopename.GetChars()); } if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor))) { SC_ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars()); } if (!stype->IsAncestorOf (actor->Class)) { SC_ScriptError ("%s is not derived from %s so cannot access its states.", actor->Class->TypeName.GetChars(), stype->TypeName.GetChars()); } } else { // No class name is stored. This allows 'virtual' jumps to // labels in subclasses. // It also means that the validity of the given state cannot // be checked here. JumpParameters.Push(NAME_None); } TArray<FName> names; MakeStateNameList(statestring, &names); if (stype != NULL) { if (!stype->ActorInfo->FindState(names.Size(), &names[0])) { SC_ScriptError("Jump to unknown state '%s' in class '%s'", statestring.GetChars(), stype->TypeName.GetChars()); } } JumpParameters.Push((ENamedName)names.Size()); for(unsigned i=0;i<names.Size();i++) { JumpParameters.Push(names[i]); } // No offsets here. The point of jumping to labels is to avoid such things! } break; case 'C': case 'c': // Color SC_MustGetString (); if (SC_Compare("none")) { v = -1; } else { int c = V_GetColor (NULL, sc_String); // 0 needs to be the default so we have to mark the color. v = MAKEARGB(1, RPART(c), GPART(c), BPART(c)); } break; case 'X': case 'x': v = ParseExpression (false, bag.Info->Class); break; case 'Y': case 'y': v = ParseExpression (true, bag.Info->Class); break; default: assert(false); v = -1; break; } StateParameters[paramindex++] = v; params++; if (varargs) { StateParameters[paramstart]++; } if (*params) { if (*params == '+') { if (SC_CheckString(")")) { goto endofstate; } params--; v = 0; StateParameters.Push(v); } else if ((islower(*params) || *params=='!') && SC_CheckString(")")) { goto endofstate; } SC_MustGetStringName (","); } } SC_MustGetStringName(")"); } else { SC_MustGetString(); if (SC_Compare("(")) { SC_ScriptError("You cannot pass parameters to '%s'\n",sc_String); } SC_UnGet(); } goto endofstate; } SC_ScriptError("Invalid state parameter %s\n", sc_String); } SC_UnGet(); endofstate: StateArray.Push(state); while (*statestrp) { int frame=((*statestrp++)&223)-'A'; if (frame<0 || frame>28) { SC_ScriptError ("Frames must be A-Z, [, \\, or ]"); frame=0; } state.Frame=(state.Frame&(SF_FULLBRIGHT|SF_BIGTIC))|frame; StateArray.Push(state); count++; } laststate=&StateArray[count]; count++; } } if (count<=minrequiredstate) { SC_ScriptError("A_Jump offset out of range in %s", actor->Class->TypeName.GetChars()); } SC_SetEscape(true); // re-enable escape sequences return count; }
/* modified */ int GetBytes(char*& p, int e[], int add, int dc) { aint val; int t = 0; while ('o') { SkipBlanks(p); if (!*p) { Error("Expression expected", 0, SUPPRESS); break; } if (t == 128) { Error("Too many arguments", p, SUPPRESS); break; } if (*p == '"') { p++; do { if (!*p || *p == '"') { Error("Syntax error", p, SUPPRESS); e[t] = -1; return t; } if (t == 128) { Error("Too many arguments", p, SUPPRESS); e[t] = -1; return t; } GetCharConstChar(p, val); check8(val); e[t++] = (val + add) & 255; } while (*p != '"'); ++p; if (dc && t) { e[t - 1] |= 128; } /* (begin add) */ } else if ((*p == 0x27) && (!*(p+2) || *(p+2) != 0x27)) { p++; do { if (!*p || *p == 0x27) { Error("Syntax error", p, SUPPRESS); e[t] = -1; return t; } if (t == 128) { Error("Too many arguments", p, SUPPRESS); e[t] = -1; return t; } GetCharConstCharSingle(p, val); check8(val); e[t++] = (val + add) & 255; } while (*p != 0x27); ++p; if (dc && t) { e[t - 1] |= 128; } /* (end add) */ } else { if (ParseExpression(p, val)) { check8(val); e[t++] = (val + add) & 255; } else { Error("Syntax error", p, SUPPRESS); break; } } SkipBlanks(p); if (*p != ',') { break; } ++p; } e[t] = -1; return t; }
SymVar* Parser::ParseDeclarator(SymType* type, bool parseParams) { SymVar* result = NULL; //pointer while (*lexer.Peek() == MULTIPLICATION) { type = new SymTypePointer(type); lexer.Get(); } //direct-declarator if (*lexer.Peek() == ROUND_LEFT_BRACKET) { lexer.Get(); result = ParseDeclarator(type); Expected(lexer.Get()->GetSubType(), ROUND_RIGHT_BRACKET); return result; } Expected(parseParams || *lexer.Peek() == IDENTIFIER, "exepcted an identifier"); if (parseParams && *lexer.Peek() != IDENTIFIER) { string n = to_string((long double)counter++); BaseToken* dummy = new BaseToken("abstract-"+n, 0, 0, IDENTIFIER, IDENTIFIER); result = new SymVar(dummy, type); } else { string msg = "redefinition: " + lexer.Peek()->GetText(); Expected(!symStack.Top()->Find(lexer.Peek()->GetText()), &msg[0]); result = new SymVar(lexer.Get(), type); } BaseToken* token = lexer.Peek(); if (*token == SQUARE_LEFT_BRACKET) { lexer.Get(); Expected(*lexer.Peek() != SQUARE_RIGHT_BRACKET, "unknown size"); SyntaxNode* index = ParseExpression(); Expected(*index->token != IDENTIFIER, "expression must have a constant value"); SymType* indexType = index->GetType(); Expected(indexType == intType && indexType->CanConvertTo(intType), "expression must be an integral constant expression"); Expected(lexer.Get()->GetSubType(), SQUARE_RIGHT_BRACKET); int size = dynamic_cast<TokenVal <int> *>(index->token)->GetValue(); result->SetType(new SymTypeArray(size, type)); } else if (*token == ROUND_LEFT_BRACKET) { lexer.Get(); SymTypeFunc* t = new SymTypeFunc(type); t->params->offset = 4; symStack.Push(t->params); ParseParameterList(); symStack.Pop(); if (*lexer.Peek() == FIGURE_LEFT_BRACKET) { parseFunc.push_back(t); t->body = ParseBlock(); parseFunc.pop_back(); } result->SetType(t); } return result; }