diff options
Diffstat (limited to 'lib/antlr/src/ANTLRUtil.cpp')
-rw-r--r-- | lib/antlr/src/ANTLRUtil.cpp | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/lib/antlr/src/ANTLRUtil.cpp b/lib/antlr/src/ANTLRUtil.cpp new file mode 100644 index 00000000..30e7ba21 --- /dev/null +++ b/lib/antlr/src/ANTLRUtil.cpp @@ -0,0 +1,163 @@ +/* ANTLR Translator Generator + * Project led by Terence Parr at http://www.jGuru.com + * Software rights: http://www.antlr.org/license.html + * + * $Id$ + */ + +#include <antlr/config.hpp> +#include <antlr/IOException.hpp> + +#include <iostream> +#include <cctype> +#include <string> + +#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE +namespace antlr { +#endif + +/** Eat whitespace from the input stream + * @param is the stream to read from + */ +ANTLR_USE_NAMESPACE(std)istream& eatwhite( ANTLR_USE_NAMESPACE(std)istream& is ) +{ + char c; + while( is.get(c) ) + { +#ifdef ANTLR_CCTYPE_NEEDS_STD + if( !ANTLR_USE_NAMESPACE(std)isspace(c) ) +#else + if( !isspace(c) ) +#endif + { + is.putback(c); + break; + } + } + return is; +} + +/** Read a string enclosed by '"' from a stream. Also handles escaping of \". + * Skips leading whitespace. + * @param in the istream to read from. + * @returns the string read from file exclusive the '"' + * @throws IOException if string is badly formatted + */ +ANTLR_USE_NAMESPACE(std)string read_string( ANTLR_USE_NAMESPACE(std)istream& in ) +{ + char ch; + ANTLR_USE_NAMESPACE(std)string ret(""); + // States for a simple state machine... + enum { START, READING, ESCAPE, FINISHED }; + int state = START; + + eatwhite(in); + + while( state != FINISHED && in.get(ch) ) + { + switch( state ) + { + case START: + // start state: check wether starting with " then switch to READING + if( ch != '"' ) + throw IOException("string must start with '\"'"); + state = READING; + continue; + case READING: + // reading state: look out for escape sequences and closing " + if( ch == '\\' ) // got escape sequence + { + state = ESCAPE; + continue; + } + if( ch == '"' ) // close quote -> stop + { + state = FINISHED; + continue; + } + ret += ch; // else append... + continue; + case ESCAPE: + switch(ch) + { + case '\\': + ret += ch; + state = READING; + continue; + case '"': + ret += ch; + state = READING; + continue; + case '0': + ret += '\0'; + state = READING; + continue; + default: // unrecognized escape is not mapped + ret += '\\'; + ret += ch; + state = READING; + continue; + } + } + } + if( state != FINISHED ) + throw IOException("badly formatted string: "+ret); + + return ret; +} + +/* Read a ([A-Z][0-9][a-z]_)* kindoff thing. Skips leading whitespace. + * @param in the istream to read from. + */ +ANTLR_USE_NAMESPACE(std)string read_identifier( ANTLR_USE_NAMESPACE(std)istream& in ) +{ + char ch; + ANTLR_USE_NAMESPACE(std)string ret(""); + + eatwhite(in); + + while( in.get(ch) ) + { +#ifdef ANTLR_CCTYPE_NEEDS_STD + if( ANTLR_USE_NAMESPACE(std)isupper(ch) || + ANTLR_USE_NAMESPACE(std)islower(ch) || + ANTLR_USE_NAMESPACE(std)isdigit(ch) || + ch == '_' ) +#else + if( isupper(ch) || islower(ch) || isdigit(ch) || ch == '_' ) +#endif + ret += ch; + else + { + in.putback(ch); + break; + } + } + return ret; +} + +/** Read a attribute="value" thing. Leading whitespace is skipped. + * Between attribute and '=' no whitespace is allowed. After the '=' it is + * permitted. + * @param in the istream to read from. + * @param attribute string the attribute name is put in + * @param value string the value of the attribute is put in + * @throws IOException if something is fishy. E.g. malformed quoting + * or missing '=' + */ +void read_AttributeNValue( ANTLR_USE_NAMESPACE(std)istream& in, + ANTLR_USE_NAMESPACE(std)string& attribute, + ANTLR_USE_NAMESPACE(std)string& value ) +{ + attribute = read_identifier(in); + + char ch; + if( in.get(ch) && ch == '=' ) + value = read_string(in); + else + throw IOException("invalid attribute=value thing "+attribute); +} + +#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE +} +#endif |