summaryrefslogtreecommitdiffabout
path: root/src/belex.l
Side-by-side diff
Diffstat (limited to 'src/belex.l') (more/less context) (ignore whitespace changes)
-rw-r--r--src/belex.l178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/belex.l b/src/belex.l
new file mode 100644
index 0000000..f35f114
--- a/dev/null
+++ b/src/belex.l
@@ -0,0 +1,178 @@
+%option nounput
+%option noinput
+
+%{
+#include "backend.h"
+
+enum {
+ T_BOGUS = 256,
+ T_IDENT,
+ T_NUMBER,
+ T_STRING,
+ T_BACKEND,
+ T_HOST,
+ T_PORT
+};
+
+static char const *input_string;
+static size_t input_len;
+static size_t input_pos;
+static char const *string_start;
+static size_t current_pos;
+
+#define YY_INPUT(buf,result,max_size) \
+ do { \
+ size_t n = input_len - input_pos; \
+ if (n > max_size) \
+ n = max_size; \
+ memcpy(buf, input_string, n); \
+ input_pos += n; \
+ result = n; \
+ } while (0)
+
+#define YY_USER_ACTION \
+ current_pos += yyleng;
+
+#define YY_DECL static int yylex(void)
+static int yywrap(void);
+
+static char const *
+input_point(void)
+{
+ return input_string + current_pos;
+}
+
+#define YYSTYPE be_string_t
+#define YYSTYPE_INITIALIZER { NULL, 0 }
+
+static YYSTYPE yylval;
+%}
+
+%x COMMENT STR
+
+%%
+ /* C-style comments */
+"/*" BEGIN(COMMENT);
+<COMMENT>[^*]* /* eat anything that's not a '*' */
+<COMMENT>"*"+[^*/]* /* eat up '*'s not followed by '/'s */
+<COMMENT>"*"+"/" BEGIN(INITIAL);
+
+ /* Single-line comments */
+"//".*\n ;
+#.*\n ;
+
+ /* Multi-line strings */
+"{\"" { BEGIN(STR); string_start = input_point(); }
+<STR>[^\"]* /* eat anything that's not a '"' */
+<STR>"\""+[^"}]* /* eat up '"'s not followed by '}'s */
+<STR>"\""+"}" { BEGIN(INITIAL);
+ yylval.start = string_start;
+ yylval.len = input_point() - yylval.start - 2;
+ return T_STRING;
+ }
+ /* Single-line strings */
+\".*\" {
+ yylval.start = input_point() - yyleng + 1;
+ yylval.len = yyleng - 2;
+ return T_STRING;
+ }
+backend return T_BACKEND;
+".host" return T_HOST;
+".port" return T_PORT;
+"{"|"}"|"="|";" return yytext[0];
+
+[a-zA-Z_][a-zA-Z0-9_.]+ {
+ yylval.start = input_point() - yyleng;
+ yylval.len = yyleng;
+ return T_IDENT;
+ }
+[0-9]+ return T_NUMBER;
+
+[ \t\n]+ ;
+
+. return T_BOGUS;
+
+%%
+int
+yywrap(void)
+{
+ return 1;
+}
+
+static void
+set_input(char const *str, size_t len)
+{
+ input_string = str;
+ input_len = len;
+ input_pos = 0;
+ current_pos = 0;
+}
+
+static int brace_nesting;
+
+static void
+read_backend(regfun_t regfun, void *d)
+{
+ int c;
+ int in_statement;
+ YYSTYPE label, host = YYSTYPE_INITIALIZER, port = YYSTYPE_INITIALIZER;
+
+ if ((c = yylex()) != T_IDENT && c != T_STRING)
+ return;
+ label = yylval;
+ if ((c = yylex()) != '{')
+ return;
+ brace_nesting++;
+ in_statement = 0;
+ while (brace_nesting == 1) {
+ c = yylex();
+ if (c == 0)
+ break;
+ else if (c == '{')
+ brace_nesting++;
+ else if (c == '}')
+ brace_nesting++;
+ else if (in_statement) {
+ if (c == ';')
+ in_statement = 0;
+ } else {
+ in_statement = 1;
+ if (c == T_HOST || c == T_PORT) {
+ YYSTYPE *stk = c == T_HOST ? &host : &port;
+ in_statement = 1;
+ if ((c = yylex()) == '=') {
+ c = yylex();
+ if (c == T_STRING || c == T_IDENT) {
+ *stk = yylval;
+ }
+ }
+ }
+ }
+ }
+ regfun(&label, &host, &port, d);
+}
+
+void
+backend_parser(const char *str, size_t len, regfun_t regfun, void *d)
+{
+ int c;
+
+ set_input(str, len);
+
+ brace_nesting = 0;
+ while ((c = yylex())) {
+ if (brace_nesting == 0) {
+ if (c == T_BACKEND) {
+ read_backend(regfun, d);
+ }
+ }
+ switch (c) {
+ case '{':
+ brace_nesting++;
+ break;
+ case '}':
+ brace_nesting--;
+ break;
+ }
+ }
+}

Return to:

Send suggestions and report system problems to the System administrator.