From: Luca Bruno Date: Fri, 30 Dec 2011 08:26:26 +0000 (+0100) Subject: parser: Allow to parse expressions/statements from string X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e7cbff0fd7ebc8912382cde727208b417106fbb1;p=thirdparty%2Fvala.git parser: Allow to parse expressions/statements from string --- diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 10c42d6d6..ee1907d36 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -29,6 +29,8 @@ public class Vala.Parser : CodeVisitor { Scanner scanner; CodeContext context; + bool compiler_code = false; + SourceReference? from_string_reference = null; // token buffer TokenInfo[] tokens; @@ -145,17 +147,28 @@ public class Vala.Parser : CodeVisitor { } SourceReference get_src (SourceLocation begin) { - int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE; + if (from_string_reference != null) { + return from_string_reference; + } + int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE; return new SourceReference (scanner.source_file, begin, tokens[last_index].end); } SourceReference get_current_src () { + if (from_string_reference != null) { + return from_string_reference; + } + var token = tokens[index]; return new SourceReference (scanner.source_file, token.begin, token.end); } SourceReference get_last_src () { + if (from_string_reference != null) { + return from_string_reference; + } + int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE; var token = tokens[last_index]; return new SourceReference (scanner.source_file, token.begin, token.end); @@ -263,6 +276,11 @@ public class Vala.Parser : CodeVisitor { } break; default: + if (compiler_code && current () == TokenType.DOT) { + next(); + next(); + return; + } throw new ParseError.SYNTAX ("expected identifier"); } } @@ -322,6 +340,54 @@ public class Vala.Parser : CodeVisitor { } } + public Expression? parse_expression_string (string str, SourceReference source_reference) { + Expression? result = null; + + compiler_code = true; + context = source_reference.file.context; + from_string_reference = source_reference; + + scanner = new Scanner.from_string (str, source_reference.file); + index = -1; + size = 0; + + next (); + + try { + result = parse_expression (); + } catch (Error e) { + Report.error (source_reference, "internal error: %s".printf (e.message)); + } + + scanner = null; + from_string_reference = null; + compiler_code = false; + + return result; + } + + public void parse_statements_string (string str, Block block, SourceReference source_reference) { + compiler_code = true; + context = source_reference.file.context; + from_string_reference = source_reference; + + scanner = new Scanner.from_string (str, source_reference.file); + index = -1; + size = 0; + + next (); + + try { + parse_statements (block); + } catch (Error e) { + Report.error (source_reference, "internal error: %s".printf (e.message)); + } + + scanner = null; + from_string_reference = null; + compiler_code = false; + } + public void parse_file (SourceFile source_file) { var has_global_context = (context != null); if (!has_global_context) { @@ -361,6 +427,9 @@ public class Vala.Parser : CodeVisitor { } void skip_symbol_name () throws ParseError { + if (compiler_code && accept (TokenType.DOT)) { + // temporary variable + } do { skip_identifier (); } while (accept (TokenType.DOT) || accept (TokenType.DOUBLE_COLON)); @@ -682,7 +751,14 @@ public class Vala.Parser : CodeVisitor { Expression parse_simple_name () throws ParseError { var begin = get_location (); - string id = parse_identifier (); + string id; + if (compiler_code && accept (TokenType.DOT)) { + // temporary variable + next (); + id = "."+get_last_string (); + } else { + id = parse_identifier (); + } bool qualified = false; if (id == "global" && accept (TokenType.DOUBLE_COLON)) { id = parse_identifier (); @@ -1590,6 +1666,10 @@ public class Vala.Parser : CodeVisitor { break; default: bool is_expr = is_expression (); + if (!is_expr && compiler_code && current () == TokenType.DOT) { + // compiler variable assignment + is_expr = true; + } if (is_expr) { stmt = parse_expression_statement (); } else { diff --git a/vala/valascanner.vala b/vala/valascanner.vala index 718b65471..6a5a38624 100644 --- a/vala/valascanner.vala +++ b/vala/valascanner.vala @@ -28,6 +28,7 @@ using GLib; */ public class Vala.Scanner { public SourceFile source_file { get; private set; } + string buffer; TokenType previous; char* current; @@ -69,6 +70,19 @@ public class Vala.Scanner { column = 1; } + public Scanner.from_string (string str, SourceFile source_file) { + this.source_file = source_file; + buffer = str; // keep alive + + char* begin = str; + end = begin + str.length; + + current = begin; + + line = 1; + column = 1; + } + public void seek (SourceLocation location) { current = location.pos; line = location.line;