From e428a288113dc87ceac66393227e25e060f62279 Mon Sep 17 00:00:00 2001 From: Jan Breuer <jan.breuer@jaybee.cz> Date: ćšć, 10 9æ 2015 06:23:18 +0800 Subject: [PATCH] Add Numeric list parsing --- libscpi/src/lexer.c | 23 ++++++- libscpi/src/lexer_private.h | 1 libscpi/inc/scpi/error.h | 2 libscpi/inc/scpi/types.h | 1 libscpi/src/expression.c | 97 ++++++++++++++++++++++++++++++++ libscpi/inc/scpi/expression.h | 11 +++ 6 files changed, 131 insertions(+), 4 deletions(-) diff --git a/libscpi/inc/scpi/error.h b/libscpi/inc/scpi/error.h index 75d1166..e9892fb 100644 --- a/libscpi/inc/scpi/error.h +++ b/libscpi/inc/scpi/error.h @@ -92,7 +92,7 @@ XE(SCPI_ERROR_BLOCK_DATA_ERROR, -160, "Block data error") \ XE(SCPI_ERROR_INVALID_BLOCK_DATA, -161, "Invalid block data") \ XE(SCPI_ERROR_BLOCK_DATA_NOT_ALLOWED, -168, "Block data not allowed") \ - XE(SCPI_ERROR_EXPRESSION_PARSING_ERROR, -170, "Expression error") \ + X(SCPI_ERROR_EXPRESSION_PARSING_ERROR, -170, "Expression error") \ XE(SCPI_ERROR_INVAL_EXPRESSION, -171, "Invalid expression") \ XE(SCPI_ERROR_EXPRESSION_DATA_NOT_ALLOWED, -178, "Expression data not allowed") \ XE(SCPI_ERROR_MACRO_DEFINITION_ERROR, -180, "Macro error") \ diff --git a/libscpi/inc/scpi/expression.h b/libscpi/inc/scpi/expression.h index dedda20..e3cb035 100644 --- a/libscpi/inc/scpi/expression.h +++ b/libscpi/inc/scpi/expression.h @@ -42,6 +42,17 @@ extern "C" { #endif + enum _scpi_expr_result_t { + SCPI_EXPR_OK = 0, + SCPI_EXPR_ERROR, + SCPI_EXPR_NO_MORE, + }; + typedef enum _scpi_expr_result_t scpi_expr_result_t; + + scpi_expr_result_t SCPI_ExprNumericListEntry(scpi_t * context, scpi_parameter_t * param, int index, scpi_bool_t * isRange, scpi_parameter_t * valueFrom, scpi_parameter_t * valueTo); + scpi_expr_result_t SCPI_ExprNumericListEntryInt(scpi_t * context, scpi_parameter_t * param, int index, scpi_bool_t * isRange, int32_t * valueFrom, int32_t * valueTo); + scpi_expr_result_t SCPI_ExprNumericListEntryDouble(scpi_t * context, scpi_parameter_t * param, int index, scpi_bool_t * isRange, double * valueFrom, double * valueTo); + #ifdef __cplusplus } #endif diff --git a/libscpi/inc/scpi/types.h b/libscpi/inc/scpi/types.h index db52e81..bded006 100644 --- a/libscpi/inc/scpi/types.h +++ b/libscpi/inc/scpi/types.h @@ -141,6 +141,7 @@ enum _scpi_token_type_t { SCPI_TOKEN_COMMA, SCPI_TOKEN_SEMICOLON, + SCPI_TOKEN_COLON, SCPI_TOKEN_QUESTION, SCPI_TOKEN_NL, SCPI_TOKEN_HEXNUM, diff --git a/libscpi/src/expression.c b/libscpi/src/expression.c index 99968cf..e0cae6c 100644 --- a/libscpi/src/expression.c +++ b/libscpi/src/expression.c @@ -34,4 +34,101 @@ */ #include "scpi/expression.h" +#include "scpi/error.h" +#include "scpi/parser.h" +#include "lexer_private.h" + +static scpi_expr_result_t numericRange(lex_state_t * state, scpi_bool_t * isRange, scpi_token_t * valueFrom, scpi_token_t * valueTo) +{ + if (scpiLex_DecimalNumericProgramData(state, valueFrom)) { + if (scpiLex_Colon(state, valueTo)) { + *isRange = TRUE; + if (scpiLex_DecimalNumericProgramData(state, valueTo)) { + return SCPI_EXPR_OK; + } else { + return SCPI_EXPR_ERROR; + } + } else { + *isRange = FALSE; + return SCPI_EXPR_OK; + } + } + + return SCPI_EXPR_NO_MORE; +} + +scpi_expr_result_t SCPI_ExprNumericListEntry(scpi_t * context, scpi_parameter_t * param, int index, scpi_bool_t * isRange, scpi_parameter_t * valueFrom, scpi_parameter_t * valueTo) +{ + lex_state_t lex; + int i; + scpi_expr_result_t res; + + if (!isRange || !valueFrom || !valueTo || !param) { + SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); + return SCPI_EXPR_ERROR; + } + + if (param->type != SCPI_TOKEN_PROGRAM_EXPRESSION) { + SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); + return SCPI_EXPR_ERROR; + } + + lex.buffer = param->ptr + 1; + lex.pos = lex.buffer; + lex.len = param->len - 2; + + for (i = 0; i <= index; i++) { + res = numericRange(&lex, isRange, valueFrom, valueTo); + if (res != SCPI_EXPR_OK) { + break; + } + if (i != index) { + if (!scpiLex_Comma(&lex, valueFrom)) { + res = SCPI_EXPR_ERROR; + break; + } + } + } + + if (res == SCPI_EXPR_ERROR) { + SCPI_ErrorPush(context, SCPI_ERROR_EXPRESSION_PARSING_ERROR); + } + return res; +} + +scpi_expr_result_t SCPI_ExprNumericListEntryInt(scpi_t * context, scpi_parameter_t * param, int index, scpi_bool_t * isRange, int32_t * valueFrom, int32_t * valueTo) +{ + scpi_expr_result_t res; + scpi_bool_t range = FALSE; + scpi_parameter_t paramFrom; + scpi_parameter_t paramTo; + + res = SCPI_ExprNumericListEntry(context, param, index, &range, ¶mFrom, ¶mTo); + if (res == SCPI_EXPR_OK) { + SCPI_ParamToInt(context, ¶mFrom, valueFrom); + if (range) { + SCPI_ParamToInt(context, ¶mTo, valueFrom); + } + } + + return res; +} + +scpi_expr_result_t SCPI_ExprNumericListEntryDouble(scpi_t * context, scpi_parameter_t * param, int index, scpi_bool_t * isRange, double * valueFrom, double * valueTo) +{ + scpi_expr_result_t res; + scpi_bool_t range = FALSE; + scpi_parameter_t paramFrom; + scpi_parameter_t paramTo; + + res = SCPI_ExprNumericListEntry(context, param, index, &range, ¶mFrom, ¶mTo); + if (res == SCPI_EXPR_OK) { + SCPI_ParamToDouble(context, ¶mFrom, valueFrom); + if (range) { + SCPI_ParamToDouble(context, ¶mTo, valueFrom); + } + } + + return res; +} diff --git a/libscpi/src/lexer.c b/libscpi/src/lexer.c index 755c4bf..512655f 100644 --- a/libscpi/src/lexer.c +++ b/libscpi/src/lexer.c @@ -865,6 +865,26 @@ } /** + * Detect token colon + * @param state + * @param token + * @return + */ +int scpiLex_Colon(lex_state_t * state, scpi_token_t * token) { + token->ptr = state->pos; + + if (skipChr(state, ':')) { + token->len = 1; + token->type = SCPI_TOKEN_COLON; + } else { + token->len = 0; + token->type = SCPI_TOKEN_UNKNOWN; + } + + return token->len; +} + +/** * Detect token New line * @param state * @param token @@ -888,6 +908,3 @@ return token->len; } - - - diff --git a/libscpi/src/lexer_private.h b/libscpi/src/lexer_private.h index 1d3a8a6..ef27989 100644 --- a/libscpi/src/lexer_private.h +++ b/libscpi/src/lexer_private.h @@ -56,6 +56,7 @@ int scpiLex_ProgramExpression(lex_state_t * state, scpi_token_t * token) LOCAL; int scpiLex_Comma(lex_state_t * state, scpi_token_t * token) LOCAL; int scpiLex_Semicolon(lex_state_t * state, scpi_token_t * token) LOCAL; + int scpiLex_Colon(lex_state_t * state, scpi_token_t * token) LOCAL; int scpiLex_NewLine(lex_state_t * state, scpi_token_t * token) LOCAL; #ifdef __cplusplus -- Gitblit v1.9.1