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, &paramFrom, &paramTo);
+    if (res == SCPI_EXPR_OK) {
+        SCPI_ParamToInt(context, &paramFrom, valueFrom);
+        if (range) {
+            SCPI_ParamToInt(context, &paramTo, 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, &paramFrom, &paramTo);
+    if (res == SCPI_EXPR_OK) {
+        SCPI_ParamToDouble(context, &paramFrom, valueFrom);
+        if (range) {
+            SCPI_ParamToDouble(context, &paramTo, 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