Exemplo n.º 1
0
Statement* Parser::readValue()
{
  switch(currentToken.id)
  {
  case Token::not_:
    {
      UnaryStatement* statement = new UnaryStatement(*includeFile);
      statement->operation = currentToken.id;
      nextToken();
      statement->operand = readValue();
      return statement;
    }
  case Token::leftParenthesis:
    {
      nextToken();
      Statement* statement = readExpression();
      expectToken(Token::rightParenthesis);
      return statement;
    }
  case Token::leftBrace:
    {
      nextToken();
      BlockStatement* statements = new BlockStatement(*includeFile);
      while(currentToken.id != Token::rightBrace)
      {
        if(currentToken.id == Token::eof)
          expectToken(Token::rightBrace);
        statements->statements.append(readStatement());
      }
      nextToken();
      return statements;
    }
  case Token::string:
    if(currentToken.value == "true")
    {
      nextToken();
      StringStatement* statement = new StringStatement(*includeFile);
      statement->value = "true";
      return statement;
    }
    else if(currentToken.value == "false")
    {
      nextToken();
      return new StringStatement(*includeFile);
    }
    else
    {
      ReferenceStatement* statement = new ReferenceStatement(*includeFile);
      readString(statement->variable);
      return statement;
    }
  default: // quotedString
    {
      StringStatement* statement = new StringStatement(*includeFile);
      readString(statement->value);
      return statement;
    }
  }
}
Exemplo n.º 2
0
void JsonSerializer::deserializeArrayBegin(const char* label)
{
	deserializeLabel(label);
	expectToken('[');
	m_is_first_in_block = true;
	deserializeToken();
}
Exemplo n.º 3
0
void JsonSerializer::deserializeLabel(const char* label)
{
	if (!m_is_first_in_block)
	{
		expectToken(',');
		deserializeToken();
	}
	else
	{
		m_is_first_in_block = false;
	}
	if (!m_is_string_token)
	{
		ErrorProxy(*this).log() << "Unexpected token \""
								<< string(m_token, m_token_size, m_allocator)
								<< "\", expected string.";
		deserializeToken();
	}
	if (compareStringN(label, m_token, m_token_size) != 0)
	{
		ErrorProxy(*this).log() << "Unexpected label \""
								<< string(m_token, m_token_size, m_allocator) << "\", expected \""
								<< label << "\".";
		deserializeToken();
	}
	deserializeToken();
	if (m_is_string_token || m_token_size != 1 || m_token[0] != ':')
	{
		ErrorProxy(*this).log() << "Unexpected label \""
								<< string(m_token, m_token_size, m_allocator) << "\", expected \""
								<< label << "\".";
		deserializeToken();
	}
	deserializeToken();
}
Exemplo n.º 4
0
void JsonSerializer::nextArrayItem()
{
	if (!m_is_first_in_block)
	{
		expectToken(',');
		deserializeToken();
	}
}
Exemplo n.º 5
0
/*
======================
ReadActionNode

Parses and creates an AIGenericNode_t with the type ACTION_NODE from a token list
The token list pointer is modified to point to the beginning of the next node text block after reading

An action node has the form:
action name( p1, p2, ... )

Where name defines the action to execute, and the parameters are surrounded by parenthesis
======================
*/
AIGenericNode_t *ReadActionNode( pc_token_list **tokenlist )
{
	pc_token_list *current = *tokenlist;
	pc_token_list *parenBegin;
	AIActionNode_t        *ret = nullptr;
	AIActionNode_t        node;
	struct AIActionMap_s  *action = nullptr;

	if ( !expectToken( "action", &current, true ) )
	{
		return nullptr;
	}

	if ( !current )
	{
		Log::Warn( "Unexpected end of file after line %d", (*tokenlist)->token.line );
		return nullptr;
	}

	action = (struct AIActionMap_s*) bsearch( current->token.string, AIActions, ARRAY_LEN( AIActions ), sizeof( *AIActions ), cmdcmp );

	if ( !action )
	{
		Log::Warn( "%s on line %d is not a valid action", current->token.string, current->token.line );
		*tokenlist = current;
		return nullptr;
	}

	parenBegin = current->next;

	memset( &node, 0, sizeof( node ) );

	BotInitNode( ACTION_NODE, action->run, &node );

	// allow dropping of parenthesis if we don't require any parameters
	if ( action->minparams == 0 && parenBegin->token.string[0] != '(' )
	{
		ret = allocNode( AIActionNode_t );
		memcpy( ret, &node, sizeof( node ) );
		*tokenlist = parenBegin;
		return ( AIGenericNode_t * ) ret;
	}

	node.params = parseFunctionParameters( &current, &node.nparams, action->minparams, action->maxparams );

	if ( !node.params && action->minparams > 0 )
	{
		return nullptr;
	}

	// create the action node
	ret = allocNode( AIActionNode_t );
	memcpy( ret, &node, sizeof( *ret ) );

	*tokenlist = current;
	return ( AIGenericNode_t * ) ret;
}
Exemplo n.º 6
0
void JsonSerializer::deserializeArrayComma()
{
	if (m_is_first_in_block)
	{
		m_is_first_in_block = false;
	}
	else
	{

		expectToken(',');
		deserializeToken();
	}
}
Exemplo n.º 7
0
void JsonSerializer::deserializeLabel(char* label, int max_length)
{
	if (!m_is_first_in_block)
	{
		expectToken(',');
		deserializeToken();
	}
	else
	{
		m_is_first_in_block = false;
	}
	if (!m_is_string_token)
	{
		ErrorProxy(*this).log() << "Unexpected token \""
								<< string(m_token, m_token_size, m_allocator)
								<< "\", expected string.";
		deserializeToken();
	}
	copyNString(label, max_length, m_token, m_token_size);
	deserializeToken();
	expectToken(':');
	deserializeToken();
}
Exemplo n.º 8
0
/*
======================
ReadNodeList

Parses and creates an AINodeList_t from a token list
The token list pointer is modified to point to the beginning of the next node text block after reading
======================
*/
AIGenericNode_t *ReadNodeList( pc_token_list **tokenlist )
{
	AINodeList_t *list;
	pc_token_list *current = *tokenlist;

	if ( !expectToken( "{", &current, true ) )
	{
		return nullptr;
	}

	list = allocNode( AINodeList_t );

	while ( Q_stricmp( current->token.string, "}" ) )
	{
		AIGenericNode_t *node = ReadNode( &current );

		if ( node && list->numNodes >= MAX_NODE_LIST )
		{
			Log::Warn( "Max selector children limit exceeded at line %d", (*tokenlist)->token.line );
			FreeNode( node );
			FreeNodeList( list );
			*tokenlist = current;
			return nullptr;
		}
		else if ( node )
		{
			list->list[ list->numNodes ] = node;
			list->numNodes++;
		}

		if ( !node )
		{
			*tokenlist = current;
			FreeNodeList( list );
			return nullptr;
		}

		if ( !current )
		{
			*tokenlist = current;
			return ( AIGenericNode_t * ) list;
		}
	}

	*tokenlist = current->next;
	return ( AIGenericNode_t * ) list;
}
Exemplo n.º 9
0
static AIExpType_t *Primary( pc_token_list **list )
{
	pc_token_list *current = *list;
	AIExpType_t *tree = nullptr;

	if ( isUnaryOp( opTypeFromToken( &current->token ) ) )
	{
		AIExpType_t *t;
		AIOp_t *op = newOp( current );
		*list = current->next;
		t = ReadConditionExpression( list, op->opType );

		if ( !t )
		{
			Log::Warn( "Missing right operand for %s on line %d", opTypeToString( op->opType ), current->token.line );
			FreeOp( op );
			return nullptr;
		}

		tree = makeExpression( op, t, nullptr );
	}
	else if ( current->token.string[0] == '(' )
	{
		*list = current->next;
		tree = ReadConditionExpression( list, OP_NONE );
		if ( !expectToken( ")", list, true ) )
		{
			return nullptr;
		}
	}
	else if ( current->token.type == tokenType_t::TT_NUMBER )
	{
		tree = ( AIExpType_t * ) newValueLiteral( list );
	}
	else if ( current->token.type == tokenType_t::TT_NAME )
	{
		tree = ( AIExpType_t * ) newValueFunc( list );
	}
	else
	{
		Log::Warn( "token %s on line %d is not valid", current->token.string, current->token.line );
	}
	return tree;
}
Exemplo n.º 10
0
int main( int argc, char *argv[] )
{
  // Open the program's source.
  if ( argc != 2 )
    usage();
  FILE *fp = fopen( argv[ 1 ], "r" );
  if ( !fp ) {
    fprintf( stderr, "Can't open file: %s\n", argv[ 1 ] );
    usage();
  }

  // Parse the whole program source into an expression object.
  // The parser uses a one-token lookahead to help parsing compound expressions.
  char tok[ MAX_TOKEN + 1 ];
  Expr *expr = parse( expectToken( tok, fp ), fp );
  
  // If this is a legal input, there shouldn't be any extra tokens at the end.
  if ( nextToken( tok, fp ) ) {
    fprintf( stderr, "line %d: unexpected token \"%s\"\n", linesRead(), tok );
    exit( EXIT_FAILURE );
  }

  fclose( fp );

  // Run the program.
  Context *ctxt = makeContext();
  char *result = expr->eval( expr, ctxt );

  // Everything evaluates to a dynamically allocated string, but we don't
  // do anything with the one out of the top-level expression.
  free( result );

  // We're done, free everything.
  freeContext( ctxt );
  expr->destroy( expr );

  return EXIT_SUCCESS;
}
Exemplo n.º 11
0
AIGenericNode_t *ReadBehaviorTreeInclude( pc_token_list **tokenlist )
{
	pc_token_list *first = *tokenlist;
	pc_token_list *current = first;

	AIBehaviorTree_t *behavior;

	if ( !expectToken( "behavior", &current, true ) )
	{
		return nullptr;
	}

	if ( !current )
	{
		Log::Warn( "Unexpected end of file after line %d", first->token.line );
		*tokenlist = current;
		return nullptr;
	}

	behavior = ReadBehaviorTree( current->token.string, currentList );

	if ( !behavior )
	{
		Log::Warn( "Could not load behavior %s on line %d", current->token.string, current->token.line );
		*tokenlist = current->next;
		return nullptr;
	}

	if ( !behavior->root )
	{
		Log::Warn( "Recursive behavior %s on line %d", current->token.string, current->token.line );
		*tokenlist = current->next;
		return nullptr;
	}

	*tokenlist = current->next;
	return ( AIGenericNode_t * ) behavior;
}
Exemplo n.º 12
0
void JsonSerializer::deserializeObjectEnd()
{
	expectToken('}');
	m_is_first_in_block = false;
	deserializeToken();
}
Exemplo n.º 13
0
void JsonSerializer::deserializeObjectBegin()
{
	m_is_first_in_block = true;
	expectToken('{');
	deserializeToken();
}
Exemplo n.º 14
0
  int HSPReadConfigFile(HSP *sp)
  {
    EnumHSPObject level[HSP_MAX_CONFIG_DEPTH + 5];
    int depth = 0;
    level[depth] = HSPOBJ_HSP;

    // could have used something like bison to make a complete parser with
    // strict rules,  but for simplicity we just allow the current object
    // to double as a state variable that determines what is allowed next.
    
    for(HSPToken *tok = readTokens(sp); tok; tok = tok->nxt) {

      if(depth > HSP_MAX_CONFIG_DEPTH) {
	// depth overrun
	parseError(sp, tok, "too many '{'s", "");
	return NO;
      }
      else if(tok->stok == HSPTOKEN_ENDOBJ) {
	// end of level, pop the stack
	if(depth > 0) --depth;
	else {
	  parseError(sp, tok, "too many '}'s ", "");
	  return NO;
	}
      }
      else switch(level[depth]) {
      case HSPOBJ_HSP:
	// must start by opening an sFlow object
	if((tok = expectToken(sp, tok, HSPTOKEN_SFLOW)) == NULL) return NO;
	if((tok = expectToken(sp, tok, HSPTOKEN_STARTOBJ)) == NULL) return NO;
	newSFlow(sp);
	level[++depth] = HSPOBJ_SFLOW;
	break;

      case HSPOBJ_SFLOW:

	switch(tok->stok) {
	case HSPTOKEN_DNSSD:
	  if((tok = expectDNSSD(sp, tok)) == NULL) return NO;
	  break;
	case HSPTOKEN_DNSSD_DOMAIN:
	  if((tok = expectDNSSD_domain(sp, tok)) == NULL) return NO;
	  break;
	case HSPTOKEN_COLLECTOR:
	  if((tok = expectToken(sp, tok, HSPTOKEN_STARTOBJ)) == NULL) return NO;
	  newCollector(sp->sFlow->sFlowSettings_file);
	  level[++depth] = HSPOBJ_COLLECTOR;
	  break;
	case HSPTOKEN_SAMPLING:
	case HSPTOKEN_PACKETSAMPLINGRATE:
	  if((tok = expectInteger32(sp, tok, &sp->sFlow->sFlowSettings_file->samplingRate, 0, 65535)) == NULL) return NO;
	  break;
	case HSPTOKEN_POLLING:
	case HSPTOKEN_COUNTERPOLLINGINTERVAL:
	  if((tok = expectInteger32(sp, tok, &sp->sFlow->sFlowSettings_file->pollingInterval, 0, 300)) == NULL) return NO;
	  break;
	case HSPTOKEN_AGENTIP:
	  if((tok = expectIP(sp, tok, &sp->sFlow->agentIP, NULL)) == NULL) return NO;
	  break;
	case HSPTOKEN_AGENT:
	  if((tok = expectDevice(sp, tok, &sp->sFlow->agentDevice)) == NULL) return NO;
	  break;
	case HSPTOKEN_SUBAGENTID:
	  if((tok = expectInteger32(sp, tok, &sp->sFlow->subAgentId, 0, HSP_MAX_SUBAGENTID)) == NULL) return NO;
	  break;
	case HSPTOKEN_UUID:
	  if((tok = expectUUID(sp, tok, sp->uuid)) == NULL) return NO;
	  break;
	case HSPTOKEN_HEADERBYTES:
	  if((tok = expectInteger32(sp, tok, &sp->sFlow->sFlowSettings_file->headerBytes, 0, HSP_MAX_HEADER_BYTES)) == NULL) return NO;
	  break;
	case HSPTOKEN_ULOGGROUP:
	  if((tok = expectInteger32(sp, tok, &sp->sFlow->sFlowSettings_file->ulogGroup, 1, 32)) == NULL) return NO;
	  break;
	case HSPTOKEN_ULOGPROBABILITY:
	  if((tok = expectDouble(sp, tok, &sp->sFlow->sFlowSettings_file->ulogProbability, 0.0, 1.0)) == NULL) return NO;
	  break;
	default:
	  parseError(sp, tok, "unexpected sFlow setting", "");
	  return NO;
	  break;
	}
	break;
	
      case HSPOBJ_COLLECTOR:
	{
	  HSPCollector *col = sp->sFlow->sFlowSettings_file->collectors;
	  switch(tok->stok) {
	  case HSPTOKEN_IP:
	    if((tok = expectIP(sp, tok, &col->ipAddr, (struct sockaddr *)&col->sendSocketAddr)) == NULL) return NO;
	    break;
	  case HSPTOKEN_UDPPORT:
	    if((tok = expectInteger32(sp, tok, &col->udpPort, 1, 65535)) == NULL) return NO;
	    break;
	  default:
	    parseError(sp, tok, "unexpected collector setting", "");
	    return NO;
	    break;
	  }
	}
	break;
	
      default:
	parseError(sp, tok, "unexpected state", "");
      }
    }

    // OK we consumed all the tokens, but we still need to run some sanity checks to make sure
    // we have a usable configuration...

    int parseOK = YES;

    if(sp->sFlow == NULL) {
      myLog(LOG_ERR, "parse error in %s : sFlow not found", sp->configFile);
      parseOK = NO;
    }
    else {
      //////////////////////// sFlow /////////////////////////
      if(sp->sFlow->agentIP.type == 0) {
	 // it may have been defined as agent=<device>
	if(sp->sFlow->agentDevice) {
	  SFLAdaptor *ad = adaptorListGet(sp->adaptorList, sp->sFlow->agentDevice);
	  if(ad && ad->ipAddr.addr) {
	    sp->sFlow->agentIP.type = SFLADDRESSTYPE_IP_V4;
	    sp->sFlow->agentIP.address.ip_v4 = ad->ipAddr;
	  }
	}
      }
      if(sp->sFlow->agentIP.type == 0) {
	 // nae luck - try to automatically choose the first non-loopback IP address
	 for(uint32_t i = 0; i < sp->adaptorList->num_adaptors; i++) {
	    SFLAdaptor *adaptor = sp->adaptorList->adaptors[i];
	    // only the non-loopback devices should be listed here, so just take the first
	    if(adaptor && adaptor->ipAddr.addr) {
	       sp->sFlow->agentIP.type = SFLADDRESSTYPE_IP_V4;
	       sp->sFlow->agentIP.address.ip_v4 = adaptor->ipAddr;
	       // fill in the device that we picked too
	       sp->sFlow->agentDevice = strdup(adaptor->deviceName);
	       break;
	    }
	 }
      }

      if(sp->sFlow->agentIP.type == SFLADDRESSTYPE_IP_V4 && sp->sFlow->agentDevice == NULL) {
	// try to fill in the device field too (because we need to give that one to open vswitch).
	for(uint32_t i = 0; i < sp->adaptorList->num_adaptors; i++) {
	  SFLAdaptor *adaptor = sp->adaptorList->adaptors[i];
	  if(adaptor && (adaptor->ipAddr.addr == sp->sFlow->agentIP.address.ip_v4.addr)) {
	    sp->sFlow->agentDevice = strdup(adaptor->deviceName);
	    break;
	  }
	}
      }

      if(sp->sFlow->agentIP.type == 0) {
        // still no agentIP.  That's a showstopper.
	myLog(LOG_ERR, "parse error in %s : agentIP not defined", sp->configFile);
	parseOK = NO;
      }
      if(sp->sFlow->sFlowSettings_file->numCollectors == 0 && sp->DNSSD == NO) {
	myLog(LOG_ERR, "parse error in %s : DNS-SD is off and no collectors are defined", sp->configFile);
	parseOK = NO;
      }
      for(HSPCollector *coll = sp->sFlow->sFlowSettings_file->collectors; coll; coll = coll->nxt) {
	//////////////////////// collector /////////////////////////
	if(coll->ipAddr.type == 0) {
	  myLog(LOG_ERR, "parse error in %s : collector  has no IP", sp->configFile);
	  parseOK = NO;
	}
      }

      if(sp->sFlow->sFlowSettings_file->ulogProbability > 0) {
	sp->sFlow->sFlowSettings_file->ulogSamplingRate = (uint32_t)(1.0 / sp->sFlow->sFlowSettings_file->ulogProbability);
      }

    }

    return parseOK;
  }
Exemplo n.º 15
0
void JsonSerializer::deserializeArrayEnd()
{
	expectToken(']');
	m_is_first_in_block = false;
	deserializeToken();
}
Exemplo n.º 16
0
void JsonSerializer::deserializeArrayBegin()
{
	expectToken('[');
	m_is_first_in_block = true;
	deserializeToken();
}
Exemplo n.º 17
0
/** Parse with one token worth of look-ahead, return the expression object representing
    the syntax parsed.
    @param tok next token from the input.
    @param fp file subsequent tokens are being read from.
    @return the expression object constructed from the input.
*/
Expr *parse( char *tok, FILE *fp )
{
  // Create a literal token for anything that looks like a number.
  {
    long dummy;
    int pos;
    // See if the whole token parses as a long int.
    if ( sscanf( tok, "%ld%n", &dummy, &pos ) == 1 &&
         pos == strlen( tok ) ) {
      // Copy the literal to a dynamically allocated string, since makeLiteral wants
      // a string it can keep.
      char *str = (char *) malloc( strlen( tok ) + 1 );
      return makeLiteral( strcpy( str, tok ) );
    }
  }

  // Create a literal token for a quoted string, without the quotes.
  if ( tok[ 0 ] == '"' ) {
    // Same as above, make a dynamically allocated copy of the token that the literal
    // expression can keep as long as at wants to.
    int len = strlen( tok );
    char *str = (char *) malloc( len - 1 );
    strncpy( str, tok + 1, len - 2 );
    str[ len - 2 ] = '\0';
    return makeLiteral( str );
  }

  // Handle compound statements
  if ( strcmp( tok, "{" ) == 0 ) {
    int len = 0;
    int cap = INITIAL_CAPACITY;
    Expr **eList = (Expr **) malloc( cap * sizeof( Expr * ) );

    // Keep parsing subexpressions until we hit the closing curly bracket.
    while ( strcmp( expectToken( tok, fp ), "}" ) != 0 ) {
      if ( len >= cap )
        eList = (Expr **) realloc( eList, ( cap *= 2 ) * sizeof( Expr * ) );
      eList[ len++ ] = parse( tok, fp );
    }

    return makeCompound( eList, len );
  }

  // Handle language operators (reserved words)

  if ( strcmp( tok, "print" ) == 0 ) {
    // Parse the one argument to print, and create a print expression.
    Expr *arg = parse( expectToken( tok, fp ), fp );
    return makePrint( arg );
  }
  
  
  if ( strcmp( tok, "set" ) == 0 ) {
    // Parse the two operands, then make a set expression with them.
    char *str = expectToken( tok, fp );
    int len = strlen( str );
    char *name = (char *) malloc( len + 1 );
    strcpy( name, str );
    name[ len ] = '\0';
    if ( !isalpha(name[0]) || strlen( name ) > MAX_VAR || strchr( name, LEFT_BRACKET ) || strchr( name, RIGHT_BRACKET ) || strchr( name, POUND ) ) {
      // Complain if we can't make sense of the variable.
      fprintf( stderr, "line %d: invalid variable name \"%s\"\n", linesRead(), name );
      exit( EXIT_FAILURE );
    }
    Expr *expr = parse( expectToken( tok, fp ), fp );
    Expr *set = makeSet
    ( name, expr );
    free(name);
    return set;
  }
  
  if ( strcmp( tok, "add" ) == 0 ) {
    // Parse the two operands, then make an add expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeAdd( op1, op2 );
  }
  
  if ( strcmp( tok, "sub" ) == 0 ) {
    // Parse the two operands, then make a sub expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeSub( op1, op2 );
  }
  
  if ( strcmp( tok, "mul" ) == 0 ) {
    // Parse the two operands, then make a mul expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeMul( op1, op2 );
  }
  
  if ( strcmp( tok, "div" ) == 0 ) {
    // Parse the two operands, then make a div expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeDiv
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "equal" ) == 0 ) {
    // Parse the two operands, then make an equal expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeEqual
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "less" ) == 0 ) {
    // Parse the two operands, then make a less expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeLess
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "not" ) == 0 ) {
    // Parse the operand, then make a not expression with it.
    Expr *op = parse( expectToken( tok, fp ), fp );
    return makeNot
    ( op );
  }
  
  if ( strcmp( tok, "and" ) == 0 ) {
    // Parse the two operands, then make an and expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeAnd
    ( op1, op2 );
  }
      
  if ( strcmp( tok, "or" ) == 0 ) {
    // Parse the two operands, then make an or expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeOr
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "if" ) == 0 ) {
    // Parse the two operands, then make an if expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeIf
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "while" ) == 0 ) {
    // Parse the two operands, then make a while expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeWhile
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "concat" ) == 0 ) {
    // Parse the two operands, then make a concatenation expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeConcat
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "substr" ) == 0 ) {
    // Parse the three operands, then make a substring expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    Expr *op3 = parse( expectToken( tok, fp ), fp );
    return makeSubstr
    ( op1, op2, op3 );
  }

  
  // Handle variables
  if ( isalpha(tok[0]) && strlen( tok ) <= MAX_VAR && !strchr( tok, LEFT_BRACKET ) && !strchr( tok, RIGHT_BRACKET ) && !strchr( tok, POUND ) ) {
    // Parse the variable name and make a variable expression.
    char *str = tok;
    int len = strlen( str );
    char *name = (char *) malloc( len + 1 );
    strcpy( name, str );
    name[ len ] = '\0';
    Expr *var = makeVariable( name );
    free(name);
    return var;
  }
  
  // Complain if we can't make sense of the token.
  fprintf( stderr, "line %d: invalid token \"%s\"\n", linesRead(), tok );
  exit( EXIT_FAILURE );
  
  // Never reached.
  return NULL;
}
Exemplo n.º 18
0
static AIValue_t *parseFunctionParameters( pc_token_list **list, int *nparams, int minparams, int maxparams )
{
	pc_token_list *current = *list;
	pc_token_list *parenBegin = current->next;
	pc_token_list *parenEnd;
	pc_token_list *parse;
	AIValue_t     *params = nullptr;
	int           numParams = 0;

	// functions should always be proceeded by a '(' if they have parameters
	if ( !expectToken( "(", &parenBegin, false ) )
	{
		*list = current;
		return nullptr;
	}

	// find the end parenthesis around the function's args
	parenEnd = findCloseParen( parenBegin, nullptr );

	if ( !parenEnd )
	{
		Log::Warn( "could not find matching ')' for '(' on line %d", parenBegin->token.line );
		*list = parenBegin->next;
		return nullptr;
	}

	// count the number of parameters
	parse = parenBegin->next;

	while ( parse != parenEnd )
	{
		if ( parse->token.type == tokenType_t::TT_NUMBER || parse->token.type == tokenType_t::TT_STRING )
		{
			numParams++;
		}
		else if ( parse->token.string[ 0 ] != ',' )
		{
			Log::Warn( "Invalid token %s in parameter list on line %d", parse->token.string, parse->token.line );
			*list = parenEnd->next; // skip invalid function expression
			return nullptr;
		}
		parse = parse->next;
	}

	// warn if too many or too few parameters
	if ( numParams < minparams )
	{
		Log::Warn( "too few parameters for %s on line %d", current->token.string, current->token.line );
		*list = parenEnd->next;
		return nullptr;
	}

	if ( numParams > maxparams )
	{
		Log::Warn( "too many parameters for %s on line %d", current->token.string, current->token.line );
		*list = parenEnd->next;
		return nullptr;
	}

	*nparams = numParams;

	if ( numParams )
	{
		// add the parameters
		params = ( AIValue_t * ) BG_Alloc( sizeof( *params ) * numParams );

		numParams = 0;
		parse = parenBegin->next;
		while ( parse != parenEnd )
		{
			if ( parse->token.type == tokenType_t::TT_NUMBER || parse->token.type == tokenType_t::TT_STRING )
			{
				params[ numParams ] = AIBoxToken( &parse->token );
				numParams++;
			}
			parse = parse->next;
		}
	}
	*list = parenEnd->next;
	return params;
}
Exemplo n.º 19
0
AIGenericNode_t *ReadDecoratorNode( pc_token_list **list )
{
	pc_token_list *current = *list;
	struct AIDecoratorMap_s *dec;
	AIDecoratorNode_t       node;
	AIDecoratorNode_t       *ret;
	pc_token_list           *parenBegin;

	if ( !expectToken( "decorator", &current, true ) )
	{
		return nullptr;
	}

	if ( !current )
	{
		Log::Warn( "Unexpected end of file after line %d", (*list)->token.line );
		*list = current;
		return nullptr;
	}

	dec = (struct AIDecoratorMap_s*) bsearch( current->token.string, AIDecorators, ARRAY_LEN( AIDecorators ), sizeof( *AIDecorators ), cmdcmp );

	if ( !dec )
	{
		Log::Warn( "%s on line %d is not a valid decorator", current->token.string, current->token.line );
		*list = current;
		return nullptr;
	}

	parenBegin = current->next;

	memset( &node, 0, sizeof( node ) );

	BotInitNode( DECORATOR_NODE, dec->run, &node );

	// allow dropping of parenthesis if we don't require any parameters
	if ( dec->minparams == 0 && parenBegin->token.string[0] != '(' )
	{
		ret = allocNode( AIDecoratorNode_t );
		memcpy( ret, &node, sizeof( node ) );
		*list = parenBegin;
		return ( AIGenericNode_t * ) ret;
	}

	node.params = parseFunctionParameters( &current, &node.nparams, dec->minparams, dec->maxparams );

	if ( !node.params && dec->minparams > 0 )
	{
		*list = current;
		return nullptr;
	}

	if ( !expectToken( "{", &current, true ) )
	{
		*list = current;
		return nullptr;
	}

	node.child = ReadNode( &current );

	if ( !node.child )
	{
		Log::Warn( "Failed to parse child node of decorator on line %d",  (*list)->token.line );
		*list = current;
		return nullptr;
	}

	if ( !expectToken( "}", &current, true ) )
	{
		*list = current;
		return nullptr;
	}

	// create the decorator node
	ret = allocNode( AIDecoratorNode_t );
	memcpy( ret, &node, sizeof( *ret ) );

	*list = current;
	return ( AIGenericNode_t * ) ret;
}
Exemplo n.º 20
0
/*
======================
ReadConditionNode

Parses and creates an AIConditionNode_t from a token list
The token list pointer is modified to point to the beginning of the next node text block

A condition node has the form:
condition [expression] {
	child node
}

or the form:
condition [expression]

[expression] can be any valid set of boolean operations and values
======================
*/
AIGenericNode_t *ReadConditionNode( pc_token_list **tokenlist )
{
	pc_token_list *current = *tokenlist;

	AIConditionNode_t *condition;

	if ( !expectToken( "condition", &current, true ) )
	{
		return nullptr;
	}

	condition = allocNode( AIConditionNode_t );
	BotInitNode( CONDITION_NODE, BotConditionNode, condition );

	condition->exp = ReadConditionExpression( &current, OP_NONE );

	if ( !current )
	{
		*tokenlist = current;
		Log::Warn( "Unexpected end of file" );
		FreeConditionNode( condition );
		return nullptr;
	}

	if ( !condition->exp )
	{
		*tokenlist = current;
		FreeConditionNode( condition );
		return nullptr;
	}

	if ( Q_stricmp( current->token.string, "{" ) )
	{
		// this condition node has no child nodes
		*tokenlist = current;
		return ( AIGenericNode_t * ) condition;
	}

	current = current->next;

	condition->child = ReadNode( &current );

	if ( !condition->child )
	{
		Log::Warn( "Failed to parse child node of condition on line %d", (*tokenlist)->token.line );
		*tokenlist = current;
		FreeConditionNode( condition );
		return nullptr;
	}

	if ( !expectToken( "}", &current, true ) )
	{
		*tokenlist = current;
		FreeConditionNode( condition );
		return nullptr;
	}

	*tokenlist = current;

	return ( AIGenericNode_t * ) condition;
}
Exemplo n.º 21
0
int TokenStream::readInt() {
    Token t;
    expectToken(t,TT_INTEGER);
    return t.ival;
}
Exemplo n.º 22
0
  int HSPReadConfigFile(HSP *sp)
  {
    EnumHSPObject level[HSP_MAX_CONFIG_DEPTH + 5];
    int depth = 0;
    level[depth] = HSPOBJ_HSP;

    // could have used something like bison to make a complete parser with
    // strict rules,  but for simplicity we just allow the current object
    // to double as a state variable that determines what is allowed next.
    
    for(HSPToken *tok = readTokens(sp); tok; tok = tok->nxt) {

      if(depth > HSP_MAX_CONFIG_DEPTH) {
	// depth overrun
	parseError(sp, tok, "too many '{'s", "");
	return NO;
      }
      else if(tok->stok == HSPTOKEN_ENDOBJ) {
	// end of level, pop the stack
	if(depth > 0) --depth;
	else {
	  parseError(sp, tok, "too many '}'s ", "");
	  return NO;
	}
      }
      else switch(level[depth]) {
	case HSPOBJ_HSP:
	  // must start by opening an sFlow object
	  if((tok = expectToken(sp, tok, HSPTOKEN_SFLOW)) == NULL) return NO;
	  if((tok = expectToken(sp, tok, HSPTOKEN_STARTOBJ)) == NULL) return NO;
	  newSFlow(sp);
	  level[++depth] = HSPOBJ_SFLOW;
	  break;

	case HSPOBJ_SFLOW:

	  switch(tok->stok) {
	  case HSPTOKEN_LOOPBACK:
	    if((tok = expectLoopback(sp, tok)) == NULL) return NO;
	    break;
	  case HSPTOKEN_DNSSD:
	    if((tok = expectDNSSD(sp, tok)) == NULL) return NO;
	    break;
	  case HSPTOKEN_DNSSD_DOMAIN:
	    if((tok = expectDNSSD_domain(sp, tok)) == NULL) return NO;
	    break;
	  case HSPTOKEN_COLLECTOR:
	    if((tok = expectToken(sp, tok, HSPTOKEN_STARTOBJ)) == NULL) return NO;
	    newCollector(sp->sFlow->sFlowSettings_file);
	    level[++depth] = HSPOBJ_COLLECTOR;
	    break;
	  case HSPTOKEN_SAMPLING:
	  case HSPTOKEN_PACKETSAMPLINGRATE:
	    if((tok = expectInteger32(sp, tok, &sp->sFlow->sFlowSettings_file->samplingRate, 0, 65535)) == NULL) return NO;
	    break;
	  case HSPTOKEN_POLLING:
	  case HSPTOKEN_COUNTERPOLLINGINTERVAL:
	    if((tok = expectInteger32(sp, tok, &sp->sFlow->sFlowSettings_file->pollingInterval, 0, 300)) == NULL) return NO;
	    break;
	  case HSPTOKEN_AGENTIP:
	    if((tok = expectIP(sp, tok, &sp->sFlow->agentIP, NULL)) == NULL) return NO;
	    sp->sFlow->explicitAgentIP = YES;
	    break;
	  case HSPTOKEN_AGENTCIDR:
	    {
	      HSPCIDR cidr = { 0 };
	      if((tok = expectCIDR(sp, tok, &cidr)) == NULL) return NO;
	      addAgentCIDR(sp->sFlow->sFlowSettings_file, &cidr);
	    }
	    break;
	  case HSPTOKEN_AGENT:
	    if((tok = expectDevice(sp, tok, &sp->sFlow->agentDevice)) == NULL) return NO;
	    sp->sFlow->explicitAgentDevice = YES;
	    break;
	  case HSPTOKEN_SUBAGENTID:
	    if((tok = expectInteger32(sp, tok, &sp->sFlow->subAgentId, 0, HSP_MAX_SUBAGENTID)) == NULL) return NO;
	    break;
	  case HSPTOKEN_UUID:
	    if((tok = expectUUID(sp, tok, sp->uuid)) == NULL) return NO;
	    break;
	  case HSPTOKEN_HEADERBYTES:
	    if((tok = expectInteger32(sp, tok, &sp->sFlow->sFlowSettings_file->headerBytes, 0, HSP_MAX_HEADER_BYTES)) == NULL) return NO;
	    break;
	  case HSPTOKEN_ULOGGROUP:
	    if((tok = expectInteger32(sp, tok, &sp->sFlow->sFlowSettings_file->ulogGroup, 1, 32)) == NULL) return NO;
	    break;
	  case HSPTOKEN_ULOGPROBABILITY:
	    if((tok = expectDouble(sp, tok, &sp->sFlow->sFlowSettings_file->ulogProbability, 0.0, 1.0)) == NULL) return NO;
	    break;
	  case HSPTOKEN_JSONPORT:
	    if((tok = expectInteger32(sp, tok, &sp->sFlow->sFlowSettings_file->jsonPort, 1025, 65535)) == NULL) return NO;
	    break;
	  default:
	    // handle wildcards here - allow sampling.<app>=<n> and polling.<app>=<secs>
	    if(tok->str && strncasecmp(tok->str, "sampling.", 9) == 0) {
	      char *app = tok->str + 9;
	      uint32_t sampling_n=0;
	      if((tok = expectInteger32(sp, tok, &sampling_n, 0, 65535)) == NULL) return NO;
	      setApplicationSampling(sp->sFlow->sFlowSettings_file, app, sampling_n);
	    }
	    else if(tok->str && strncasecmp(tok->str, "polling.", 8) == 0) {
	      char *app = tok->str + 8;
	      uint32_t polling_secs=0;
	      if((tok = expectInteger32(sp, tok, &polling_secs, 0, 300)) == NULL) return NO;
	      setApplicationPolling(sp->sFlow->sFlowSettings_file, app, polling_secs);
	    }
	    else {
	      parseError(sp, tok, "unexpected sFlow setting", "");
	      return NO;
	    }
	    break;
	  }
	  break;
	
	case HSPOBJ_COLLECTOR:
	  {
	    HSPCollector *col = sp->sFlow->sFlowSettings_file->collectors;
	    switch(tok->stok) {
	    case HSPTOKEN_IP:
	      if((tok = expectIP(sp, tok, &col->ipAddr, (struct sockaddr *)&col->sendSocketAddr)) == NULL) return NO;
	      break;
	    case HSPTOKEN_UDPPORT:
	      if((tok = expectInteger32(sp, tok, &col->udpPort, 1, 65535)) == NULL) return NO;
	      break;
	    default:
	      parseError(sp, tok, "unexpected collector setting", "");
	      return NO;
	      break;
	    }
	  }
	  break;
	
	default:
	  parseError(sp, tok, "unexpected state", "");
	}
    }

    // OK we consumed all the tokens, but we still need to run some sanity checks to make sure
    // we have a usable configuration...

    int parseOK = YES;

    if(sp->sFlow == NULL) {
      myLog(LOG_ERR, "parse error in %s : sFlow not found", sp->configFile);
      parseOK = NO;
    }
    else {
      if(sp->sFlow->sFlowSettings_file->numCollectors == 0 && sp->DNSSD == NO) {
	myLog(LOG_ERR, "parse error in %s : DNS-SD is off and no collectors are defined", sp->configFile);
	parseOK = NO;
      }
      for(HSPCollector *coll = sp->sFlow->sFlowSettings_file->collectors; coll; coll = coll->nxt) {
	//////////////////////// collector /////////////////////////
	if(coll->ipAddr.type == 0) {
	  myLog(LOG_ERR, "parse error in %s : collector  has no IP", sp->configFile);
	  parseOK = NO;
	}
      }

      if(sp->sFlow->sFlowSettings_file->ulogProbability > 0) {
	sp->sFlow->sFlowSettings_file->ulogSamplingRate = (uint32_t)(1.0 / sp->sFlow->sFlowSettings_file->ulogProbability);
      }

    }

    return parseOK;
  }