Update lexer, start of implementing parser
| | |
| | | TokProgramExpression, |
| | | TokCompoundProgramHeader, |
| | | TokCommonProgramHeader, |
| | | TokCompoundQueryProgramHeader, |
| | | TokCommonQueryProgramHeader, |
| | | TokWhiteSpace, |
| | | TokUnknown, |
| | | }; |
| | |
| | | |
| | | |
| | | int SCPI_LexWhiteSpace(lex_state_t * state, token_t * token); |
| | | int SCPI_LexCommonProgramHeader(lex_state_t * state, token_t * token); |
| | | int SCPI_LexCompoundProgramHeader(lex_state_t * state, token_t * token); |
| | | int SCPI_LexProgramHeader(lex_state_t * state, token_t * token); |
| | | int SCPI_LexQuestion(lex_state_t * state, token_t * token); |
| | | int SCPI_LexCharacterProgramData(lex_state_t * state, token_t * token); |
| | |
| | | } |
| | | |
| | | /* 7.6.1 <COMMAND PROGRAM HEADER> */ |
| | | int SCPI_LexCommonProgramHeader(lex_state_t * state, token_t * token) { |
| | | token->ptr = state->pos; |
| | | |
| | | static int skipCommonProgramHeader(lex_state_t * state) { |
| | | if (skipStar(state)) { |
| | | if(!skipProgramMnemonic(state)) { |
| | | state->pos--; |
| | | } else { |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | token->len = state->pos - token->ptr; |
| | | |
| | | if((token->len > 0)) { |
| | | token->type = TokCommonProgramHeader; |
| | | } else { |
| | | token->type = TokUnknown; |
| | | state->pos = token->ptr; |
| | | token->len = 0; |
| | | } |
| | | |
| | | return token->len; |
| | | return 0; |
| | | } |
| | | |
| | | int SCPI_LexCompoundProgramHeader(lex_state_t * state, token_t * token) { |
| | | token->ptr = state->pos; |
| | | static int skipCompoundProgramHeader(lex_state_t * state) { |
| | | const char * rollback = state->pos; |
| | | |
| | | skipColon(state); |
| | | |
| | | if(skipProgramMnemonic(state)) { |
| | | while(skipColon(state)) { |
| | | if(!skipProgramMnemonic(state)) { |
| | | // TODO: lexer error |
| | | break; |
| | | state->pos = rollback; |
| | | return 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | token->len = state->pos - token->ptr; |
| | | |
| | | if((token->len > 0)) { |
| | | token->type = TokCompoundProgramHeader; |
| | | return 1; |
| | | } else { |
| | | token->type = TokUnknown; |
| | | state->pos = token->ptr; |
| | | token->len = 0; |
| | | state->pos = rollback; |
| | | return 0; |
| | | } |
| | | |
| | | return token->len; |
| | | } |
| | | |
| | | int SCPI_LexProgramHeader(lex_state_t * state, token_t * token) { |
| | | int res; |
| | | |
| | | res = SCPI_LexCommonProgramHeader(state, token); |
| | | if(res > 0) return res; |
| | | |
| | | res = SCPI_LexCompoundProgramHeader(state, token); |
| | | if(res > 0) return res; |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int SCPI_LexQuestion(lex_state_t * state, token_t * token) { |
| | | token->ptr = state->pos; |
| | | token->type = TokUnknown; |
| | | |
| | | if (skipChr(state, '?')) { |
| | | token->len = 1; |
| | | token->type = TokQuiestion; |
| | | } else { |
| | | token->len = 0; |
| | | token->type = TokUnknown; |
| | | if(skipCommonProgramHeader(state)) { |
| | | if (skipChr(state, '?')) { |
| | | token->type = TokCommonQueryProgramHeader; |
| | | } else { |
| | | token->type = TokCommonProgramHeader; |
| | | } |
| | | } else if(skipCompoundProgramHeader(state)) { |
| | | if (skipChr(state, '?')) { |
| | | token->type = TokCompoundQueryProgramHeader; |
| | | } else { |
| | | token->type = TokCompoundProgramHeader; |
| | | } |
| | | } |
| | | |
| | | return token->len; |
| | | if (token->type != TokUnknown) { |
| | | token->len = state->pos - token->ptr; |
| | | } else { |
| | | token->len = 0; |
| | | state->pos = token->ptr; |
| | | } |
| | | |
| | | return token->len; |
| | | } |
| | | |
| | | /* 7.7.1 <CHARACTER PROGRAM DATA> */ |
| | |
| | | |
| | | #include "scpi/config.h" |
| | | #include "scpi/parser.h" |
| | | #include "scpi/lexer.h" |
| | | #include "utils.h" |
| | | #include "scpi/error.h" |
| | | |
| | |
| | | |
| | | return FALSE; |
| | | } |
| | | |
| | | |
| | | |
| | | void SCPI_ProgramMessageUnit(scpi_t * context) { |
| | | lex_state_t state; |
| | | token_t tmp; |
| | | token_t header; |
| | | token_t token; |
| | | |
| | | state.buffer = state.pos = context->buffer.data; |
| | | state.len = context->buffer.position; |
| | | |
| | | /* ignore whitespace at the begginig */ |
| | | SCPI_LexWhiteSpace(&state, &tmp); |
| | | |
| | | SCPI_LexProgramHeader(&state, &header); |
| | | |
| | | SCPI_LexWhiteSpace(&state, &tmp); |
| | | |
| | | SCPI_ParseProgramDate(context, &state, &token); |
| | | |
| | | SCPI_LexWhiteSpace(&state, &tmp); |
| | | |
| | | { |
| | | SCPI_LexComma(&state, &token); |
| | | |
| | | SCPI_LexWhiteSpace(&state, &tmp); |
| | | |
| | | SCPI_ParseProgramDate(context, &state); |
| | | |
| | | SCPI_LexWhiteSpace(&state, &tmp); |
| | | } |
| | | |
| | | SCPI_LexNewLine(&state, &tmp); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | |
| | | |
| | | |
| | | programMessageUnit |
| | | : WS* programHeader QUESTION? (WS programData (COMMA programData)*)? |
| | | : WS* programHeader (WS programData (COMMA programData)*)? |
| | | ; |
| | | |
| | | programHeader |
| | |
| | | ; |
| | | |
| | | compoundProgramHeader |
| | | : COLON? PROGRAM_MNEMONIC (COLON PROGRAM_MNEMONIC)* |
| | | : COLON? PROGRAM_MNEMONIC (COLON PROGRAM_MNEMONIC)* QUESTION? |
| | | ; |
| | | |
| | | commonProgramHeader |
| | | : STAR PROGRAM_MNEMONIC |
| | | : STAR PROGRAM_MNEMONIC QUESTION? |
| | | ; |
| | | |
| | | programDataSeparator |
| | |
| | | case TokProgramExpression: return "TokProgramExpression"; |
| | | case TokCompoundProgramHeader: return "TokCompoundProgramHeader"; |
| | | case TokCommonProgramHeader: return "TokCommonProgramHeader"; |
| | | case TokCompoundQueryProgramHeader: return "TokCompoundQueryProgramHeader"; |
| | | case TokCommonQueryProgramHeader: return "TokCommonQueryProgramHeader"; |
| | | case TokWhiteSpace: return "TokWhiteSpace"; |
| | | default: return "TokUnknown"; |
| | | } |
| | |
| | | |
| | | |
| | | void testWhiteSpace(void) { |
| | | TEST_TOKEN(" \t MEA", SCPI_LexWhiteSpace, 0, 4, TokWhiteSpace); |
| | | TEST_TOKEN(" \t MEAS", SCPI_LexWhiteSpace, 0, 4, TokWhiteSpace); |
| | | TEST_TOKEN("MEAS", SCPI_LexWhiteSpace, 0, 0, TokUnknown); |
| | | } |
| | | |
| | | void testNondecimal(void) { |
| | |
| | | } |
| | | |
| | | void testProgramHeader(void) { |
| | | TEST_TOKEN("*IDN? ", SCPI_LexCommonProgramHeader, 0, 4, TokCommonProgramHeader); |
| | | TEST_TOKEN("*?; ", SCPI_LexCommonProgramHeader, 0, 0, TokUnknown); |
| | | TEST_TOKEN("MEAS:VOLT:DC? ", SCPI_LexCommonProgramHeader, 0, 0, TokUnknown); |
| | | TEST_TOKEN("MEAS:VOLT:DC? ", SCPI_LexCompoundProgramHeader, 0, 12, TokCompoundProgramHeader); |
| | | TEST_TOKEN(":MEAS:VOLT:DC? ", SCPI_LexCompoundProgramHeader, 0, 13, TokCompoundProgramHeader); |
| | | TEST_TOKEN(":MEAS::VOLT:DC? ", SCPI_LexCompoundProgramHeader, 0, 6, TokCompoundProgramHeader); |
| | | TEST_TOKEN(":MEAS::VOLT:DC? ", SCPI_LexProgramHeader, 0, 6, TokCompoundProgramHeader); |
| | | TEST_TOKEN("*IDN?", SCPI_LexProgramHeader, 0, 4, TokCommonProgramHeader); |
| | | TEST_TOKEN("*IDN? ", SCPI_LexProgramHeader, 0, 5, TokCommonQueryProgramHeader); |
| | | TEST_TOKEN("*RST ", SCPI_LexProgramHeader, 0, 4, TokCommonProgramHeader); |
| | | TEST_TOKEN("*?; ", SCPI_LexProgramHeader, 0, 0, TokUnknown); |
| | | TEST_TOKEN("MEAS:VOLT:DC? ", SCPI_LexProgramHeader, 0, 13, TokCompoundQueryProgramHeader); |
| | | TEST_TOKEN("CONF:VOLT:DC ", SCPI_LexProgramHeader, 0, 12, TokCompoundProgramHeader); |
| | | TEST_TOKEN(":MEAS:VOLT:DC? ", SCPI_LexProgramHeader, 0, 14, TokCompoundQueryProgramHeader); |
| | | TEST_TOKEN(":MEAS::VOLT:DC? ", SCPI_LexProgramHeader, 0, 0, TokUnknown); |
| | | TEST_TOKEN("*IDN?", SCPI_LexProgramHeader, 0, 5, TokCommonQueryProgramHeader); |
| | | TEST_TOKEN("*RST", SCPI_LexProgramHeader, 0, 4, TokCommonProgramHeader); |
| | | } |
| | | |
| | | void testArbitraryBlock(void) { |