diff options
author | Johan Dahlin <johan@gnome.org> | 2008-03-25 20:53:32 +0000 |
---|---|---|
committer | Johan Dahlin <johan@src.gnome.org> | 2008-03-25 20:53:32 +0000 |
commit | 66ab1202b6499e030c32c9d0d3432e0b09bee7db (patch) | |
tree | ad2a54a99ea71cf5c42afd03810a761f09096fb8 /giscanner/scannerlexer.l | |
parent | 07d433428ed39ef43d0204cb44a75cb31d38016a (diff) | |
download | gobject-introspection-66ab1202b6499e030c32c9d0d3432e0b09bee7db.tar.gz |
Move the scanner to a separate library.
2008-03-25 Johan Dahlin <johan@gnome.org>
* Makefile.am:
* configure.ac:
* giscanner/Makefile.am:
* giscanner/sourcescanner.c:
* giscanner/sourcescanner.h:
* tools/Makefile.am:
* tools/grealpath.h:
* tools/sourcescanner.c:
* tools/sourcescanner.h:
Move the scanner to a separate library.
svn path=/trunk/; revision=164
Diffstat (limited to 'giscanner/scannerlexer.l')
-rw-r--r-- | giscanner/scannerlexer.l | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/giscanner/scannerlexer.l b/giscanner/scannerlexer.l new file mode 100644 index 00000000..03455d73 --- /dev/null +++ b/giscanner/scannerlexer.l @@ -0,0 +1,394 @@ +/* -*- Mode: C -*- +/* GObject introspection: C lexer + * + * Copyright (c) 1997 Sandro Sigala <ssigala@globalnet.it> + * Copyright (c) 2007-2008 Jürg Billeter <j@bitron.ch> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +%{ +#include <ctype.h> +#include <stdio.h> + +#include <glib.h> +#include "sourcescanner.h" +#include "scannerparser.h" +#include "grealpath.h" + +int lineno; + +extern int yylex (GISourceScanner *scanner); +#define YY_DECL int yylex (GISourceScanner *scanner) +static int yywrap (void); +static void parse_comment (GISourceScanner *scanner); +static void process_directive (GISourceScanner *scanner); +static int check_identifier (GISourceScanner *scanner, const char *); +%} + +intsuffix ([uU][lL]?)|([lL][uU]?) +fracconst ([0-9]*\.[0-9]+)|([0-9]+\.) +exppart [eE][-+]?[0-9]+ +floatsuffix [fFlL] +chartext ([^\'])|(\\.) +stringtext ([^\"])|(\\.) + +%% + +"\n" { ++lineno; } /* " */ +[\t\f\v\r ]+ { /* Ignore whitespace. */ } + +"/*" { parse_comment(scanner); } +"//".* { } + +"#define "[a-zA-Z_][a-zA-Z_0-9]*"(" { yyless (yyleng - 1); return FUNCTION_MACRO; } +"#define "[a-zA-Z_][a-zA-Z_0-9]* { return OBJECT_MACRO; } + +"#" { process_directive(scanner); } + +"{" { return '{'; } +"<%" { return '{'; } +"}" { return '}'; } +"%>" { return '}'; } +"[" { return '['; } +"<:" { return '['; } +"]" { return ']'; } +":>" { return ']'; } +"(" { return '('; } +")" { return ')'; } +";" { return ';'; } +":" { return ':'; } +"..." { return ELLIPSIS; } +"?" { return '?'; } +"." { return '.'; } +"+" { return '+'; } +"-" { return '-'; } +"*" { return '*'; } +"/" { return '/'; } +"%" { return '%'; } +"^" { return '^'; } +"&" { return '&'; } +"|" { return '|'; } +"~" { return '~'; } +"!" { return '!'; } +"=" { return '='; } +"<" { return '<'; } +">" { return '>'; } +"+=" { return ADDEQ; } +"-=" { return SUBEQ; } +"*=" { return MULEQ; } +"/=" { return DIVEQ; } +"%=" { return MODEQ; } +"^=" { return XOREQ; } +"&=" { return ANDEQ; } +"|=" { return OREQ; } +"<<" { return SL; } +">>" { return SR; } +"<<=" { return SLEQ; } +">>=" { return SREQ; } +"==" { return EQ; } +"!=" { return NOTEQ; } +"<=" { return LTEQ; } +">=" { return GTEQ; } +"&&" { return ANDAND; } +"||" { return OROR; } +"++" { return PLUSPLUS; } +"--" { return MINUSMINUS; } +"," { return ','; } +"->" { return ARROW; } + +[a-zA-Z_][a-zA-Z_0-9]* { if (scanner->macro_scan) return IDENTIFIER; else REJECT; } + +"auto" { return AUTO; } +"_Bool" { return BOOL; } +"break" { return BREAK; } +"case" { return CASE; } +"char" { return CHAR; } +"const" { return CONST; } +"continue" { return CONTINUE; } +"default" { return DEFAULT; } +"do" { return DO; } +"double" { return DOUBLE; } +"else" { return ELSE; } +"enum" { return ENUM; } +"extern" { return EXTERN; } +"float" { return FLOAT; } +"for" { return FOR; } +"goto" { return GOTO; } +"if" { return IF; } +"inline" { return INLINE; } +"int" { return INT; } +"long" { return LONG; } +"register" { return REGISTER; } +"restrict" { return RESTRICT; } +"return" { return RETURN; } +"short" { return SHORT; } +"signed" { return SIGNED; } +"sizeof" { return SIZEOF; } +"static" { return STATIC; } +"struct" { return STRUCT; } +"switch" { return SWITCH; } +"typedef" { return TYPEDEF; } +"union" { return UNION; } +"unsigned" { return UNSIGNED; } +"void" { return VOID; } +"volatile" { return VOLATILE; } +"while" { return WHILE; } + +[a-zA-Z_][a-zA-Z_0-9]* { return check_identifier(scanner, yytext); } + +"0"[xX][0-9a-fA-F]+{intsuffix}? { return INTEGER; } +"0"[0-7]+{intsuffix}? { return INTEGER; } +[0-9]+{intsuffix}? { return INTEGER; } + +{fracconst}{exppart}?{floatsuffix}? { return FLOATING; } +[0-9]+{exppart}{floatsuffix}? { return FLOATING; } + +"'"{chartext}*"'" { return CHARACTER; } +"L'"{chartext}*"'" { return CHARACTER; } + +"\""{stringtext}*"\"" { return STRING; } +"L\""{stringtext}*"\"" { return STRING; } + +. { fprintf(stderr, "%s:%d: unexpected character `%c'\n", scanner->current_filename, lineno, yytext[0]); } + +%% + +static int +yywrap (void) +{ + return 1; +} + + +static void +parse_gtkdoc (GISourceScanner *scanner, + gchar *symbol, + int *c1, + int *c2) +{ + gboolean isline = FALSE; + gchar line[256]; + int i; + gchar **parts; + GISourceDirective *directive; + char *name,*value; + GSList *directives; + GSList *options = NULL; + char *rname; + + i = 0; + do + { + *c1 = *c2; + if (*c1 == '\n') + { + isline = TRUE; + break; + } + if (i >= 256) + break; + line[i++] = *c1; + *c2 = input(); + } while (*c2 != EOF && !(*c1 == '*' && *c2 == '/')); + + if (!isline) + return; + + line[i] = '\0'; + + parts = g_strsplit (line, ": ", 3); + + if (g_strv_length (parts) >= 2) + { + name = parts[0]; + + if (g_strv_length (parts) == 3) + { + char *ptr = parts[1]; + GString *current = NULL; + gboolean open = (*ptr == '('); + + current = g_string_new (""); + value = parts[2]; + + while (*ptr++) + { + if (*ptr == '(') + open = TRUE; + else if (*ptr != ')' && open) + g_string_append_c (current, *ptr); + else if (*ptr == ')') { + options = g_slist_prepend (options, g_strdup (current->str)); + open = FALSE; + } + } + g_string_free (current, TRUE); + } + else + value = parts[1]; + } + else /* parts == 1 */ + { + name = parts[0]; + value = NULL; + } + + /* + * This is a special case for return values, name will only be + * 'eturn' or a valid name, check the call site. + * Context-sensitive parsing would probably be the right way to go + */ + if (g_ascii_strncasecmp ("eturn", name, 5) == 0) + rname = "return"; + else + rname = name; + + directive = gi_source_directive_new (rname, value, options); + directives = g_hash_table_lookup (scanner->directives_map, symbol); + directives = g_slist_prepend (directives, directive); + g_hash_table_replace (scanner->directives_map, + g_strdup (symbol), directives); + + g_strfreev (parts); + +} + + +static void +parse_comment (GISourceScanner *scanner) +{ + GString *symbol = NULL; + gboolean startofline = FALSE, have_symbol = FALSE, start1 = FALSE, start_symbol = FALSE; + int c1, c2; + + c1 = input(); + c2 = input(); + + while (c2 != EOF && !(c1 == '*' && c2 == '/')) + { + if (c1 == ':') + have_symbol = TRUE; + else if (c1 == '\n') + start1 = TRUE; + else if (c1 == '*' && start1) + start_symbol = TRUE; + else if (!have_symbol && start_symbol) + { + if (!symbol) + symbol = g_string_new (""); + if (c1 != ' ') + g_string_append_c (symbol, c1); + } + + if (c1 == '\n') + { + ++lineno; + startofline = TRUE; + } + + c1 = c2; + c2 = input(); + + if ((c1 != '*' && c1 != ' ')) + startofline = FALSE; + + if (startofline && (c1 == ' ') && (c2 == '@' || (c2 == 'r') || (c2 == 'R'))) + { + c1 = c2; + c2 = input(); + if (symbol) + parse_gtkdoc (scanner, symbol->str, &c1, &c2); + } + } + + if (symbol) + g_string_free (symbol, TRUE); + +} + +static int +check_identifier (GISourceScanner *scanner, + const char *s) +{ + /* + * This function checks if `s' is a type name or an + * identifier. + */ + + if (gi_source_scanner_is_typedef (scanner, s)) { + return TYPEDEF_NAME; + } else if (strcmp (s, "__builtin_va_list") == 0) { + return TYPEDEF_NAME; + } + + return IDENTIFIER; +} + +static void +process_directive (GISourceScanner *scanner) +{ + /* extract current filename from #line directives */ + GString *filename_builder; + gboolean in_string, found_filename; + + lineno = 0; + found_filename = FALSE; + in_string = FALSE; + filename_builder = g_string_new (""); + + int c = input (); + while (c != EOF && c != '\n') { + if (!in_string) { + if (c == '\"') { + in_string = TRUE; + found_filename = TRUE; + } else if (c >= '0' && c <= '9') { + if (!found_filename) { + lineno = lineno * 10 + (c - '0'); + } + } + } else { + if (c == '\"') { + in_string = FALSE; + } else if (c == '\\') { + g_string_append_c (filename_builder, c); + c = input (); + g_string_append_c (filename_builder, c); + } else { + g_string_append_c (filename_builder, c); + } + } + c = input (); + } + + if (filename_builder->len > 0) { + char *filename = g_strcompress (filename_builder->str); + g_free (scanner->current_filename); + scanner->current_filename = g_realpath(filename); + g_free(filename); + } + + g_string_free (filename_builder, TRUE); +} + |