Working parser for rpcgen files.
[portablexdr.git] / rpcgen_scan.l
diff --git a/rpcgen_scan.l b/rpcgen_scan.l
new file mode 100644 (file)
index 0000000..061dbbf
--- /dev/null
@@ -0,0 +1,157 @@
+/* -*- C -*-
+ * rpcgen - Generate XDR bindings automatically.
+ * Copyright (C) 2008 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+%{
+#include <config.h>
+#include "rpcgen_parse.h"
+#include "rpcgen_int.h"
+%}
+
+%option noyywrap
+%option nounput
+%option yylineno
+
+HEXLIT     "0x"[0-9a-fA-F]+
+DECLIT     0|[1-9][0-9]*
+INTLIT     {HEXLIT}|{DECLIT}
+IDENT      [a-zA-Z_][a-zA-Z_0-9]*
+WS         [[:space:]]+
+
+%x cstring
+
+%%
+
+ /* # lineno "filename"
+  * cpp itself sets file and line numbers using these directives.  We
+  * have to parse this ourselves, since these could occur anywhere in
+  * the input, eg. in the middle of a struct definition.
+  */
+^"#".*\n    {
+  char *filename;
+  int lineno;
+
+  /* Allocate enough space to store the returned filename string. */
+  filename = malloc (strlen (yytext));
+  if (filename == NULL) perrorf ("malloc");
+
+  if (sscanf (yytext+2, "%d \"%[^\"]\"", &lineno, filename) == 2) {
+    yylineno = lineno - 1;
+    free (input_filename);
+    input_filename = filename;
+  }
+  else free (filename);
+ }
+
+ /* Anything on a line beginning with % is passed to the output.  Again
+  * we have to handle this within the scanner.
+  */
+^"%".*\n   fputs (yytext+1, yyout);
+
+ /* C string constants. */
+\"         start_string(); BEGIN (cstring);
+<cstring>{
+  \"       BEGIN (INITIAL); yylval.str = end_string(); return STRLIT;
+
+  \n       error ("unterminated string constant");
+  <<EOF>>  error ("unterminated string constant");
+
+  \\[0-7]{1,3} {
+    /* octal escape sequence */
+    int result;
+
+    (void) sscanf (yytext + 1, "%o", &result);
+
+    if (result > 0xff)
+      error ("octal constant is out of range");
+
+    add_char (result);
+  }
+
+  /* Does C allow these?? Maybe confusing it with OCaml.
+  \\x[0-9a-fA-F]{2} {
+    int result;
+
+    (void) sscanf( yytext + 1, "%x", &result );
+
+    add_char (result);
+  } */
+
+  \\[0-9]+ {
+    /* generate error - bad escape sequence; something
+     * like '\48' or '\0777777'
+     */
+    error ("bad escape sequence: %s\n", yytext);
+  }
+
+  \\n  add_char ('\n');
+  \\t  add_char ('\t');
+  \\r  add_char ('\r');
+  \\b  add_char ('\b');
+  \\f  add_char ('\f');
+
+  /* Backslash followed by a literal newline character. */
+  \\\n add_char ('\n');
+
+  /* Unrecognised escape character - should be an error? */
+  \\.  add_char (yytext[1]);
+
+  [^\\\n\"]+ {
+    add_string (yytext);
+  }
+}
+
+ /* Keywords. */
+struct     return STRUCT;
+enum       return ENUM;
+const      return CONST;
+typedef    return TYPEDEF;
+union      return UNION;
+switch     return SWITCH;
+case       return CASE;
+default    return DEFAULT;
+program    return PROGRAM;
+
+unsigned   return UNSIGNED;
+signed     return SIGNED;
+char       return CHAR;
+short      return SHORT;
+int        return INT;
+hyper      return HYPER;
+double     return DOUBLE;
+string     return STRING;
+opaque     return OPAQUE;
+
+void       return VOID;
+
+ /* Identifiers. */
+{IDENT}    { yylval.str = strdup (yytext); return IDENT; }
+
+ /* Numeric constants are tricky to scan accurately, so keep them as
+  * strings and pass them through directly to the C compiler.
+  */
+{INTLIT}   { yylval.str = strdup (yytext); return INTLIT; }
+
+ /* Single characters with special meaning. */
+":"|";"|","|"{"|"}"|"("|")"|"["|"]"|"<"|">"|"="|"*" return yytext[0];
+
+ /* Ignore whitespace. */
+{WS}
+
+ /* Anything else is an error. */
+.          error ("invalid character in input near '%c'", yytext[0]);