From 9be852e2e9622a87d9b145fe6fe4218e23343d66 Mon Sep 17 00:00:00 2001 From: Laurent Le Brun Date: Thu, 28 May 2015 08:44:51 +0000 Subject: Parser cleanup: Introduce an enum instead of the booleans -- MOS_MIGRATED_REVID=94649435 --- .../google/devtools/build/lib/syntax/Parser.java | 76 +++++++++++++--------- 1 file changed, 46 insertions(+), 30 deletions(-) (limited to 'src/main/java/com/google/devtools/build') diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java index 67e13e537c..c2642597a3 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java @@ -14,6 +14,10 @@ package com.google.devtools.build.lib.syntax; +import static com.google.devtools.build.lib.syntax.Parser.ParsingMode.BUILD; +import static com.google.devtools.build.lib.syntax.Parser.ParsingMode.PYTHON; +import static com.google.devtools.build.lib.syntax.Parser.ParsingMode.SKYLARK; + import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Supplier; @@ -66,8 +70,20 @@ class Parser { } } + /** + * ParsingMode is used to select which features the parser should accept. + */ + public enum ParsingMode { + /** Used for parsing BUILD files */ + BUILD, + /** Used for parsing .bzl files */ + SKYLARK, + /** Used for syntax checking, ignoring all Python blocks (e.g. def, class, try) */ + PYTHON, + } + private static final EnumSet STATEMENT_TERMINATOR_SET = - EnumSet.of(TokenKind.EOF, TokenKind.NEWLINE); + EnumSet.of(TokenKind.EOF, TokenKind.NEWLINE); private static final EnumSet LIST_TERMINATOR_SET = EnumSet.of(TokenKind.EOF, TokenKind.RBRACKET, TokenKind.SEMI); @@ -99,9 +115,7 @@ class Parser { private final Lexer lexer; private final EventHandler eventHandler; private final List comments; - private final boolean parsePython; - /** Whether advanced language constructs are allowed */ - private boolean skylarkMode = false; + private final ParsingMode parsingMode; private static final Map binaryOperators = new ImmutableMap.Builder() @@ -147,11 +161,14 @@ class Parser { private List includedFiles; - private Parser(Lexer lexer, EventHandler eventHandler, CachingPackageLocator locator, - boolean parsePython) { + private Parser( + Lexer lexer, + EventHandler eventHandler, + CachingPackageLocator locator, + ParsingMode parsingMode) { this.lexer = lexer; this.eventHandler = eventHandler; - this.parsePython = parsePython; + this.parsingMode = parsingMode; this.tokens = lexer.getTokens().iterator(); this.comments = new ArrayList<>(); this.locator = locator; @@ -161,12 +178,7 @@ class Parser { } private Parser(Lexer lexer, EventHandler eventHandler, CachingPackageLocator locator) { - this(lexer, eventHandler, locator, false /* parsePython */); - } - - public Parser setSkylarkMode(boolean skylarkMode) { - this.skylarkMode = skylarkMode; - return this; + this(lexer, eventHandler, locator, BUILD); } /** @@ -174,12 +186,12 @@ class Parser { * encountered during parsing are reported via "reporter". */ public static ParseResult parseFile( - Lexer lexer, EventHandler eventHandler, CachingPackageLocator locator, - boolean parsePython) { - Parser parser = new Parser(lexer, eventHandler, locator, parsePython); + Lexer lexer, EventHandler eventHandler, CachingPackageLocator locator, boolean parsePython) { + ParsingMode parsingMode = parsePython ? PYTHON : BUILD; + Parser parser = new Parser(lexer, eventHandler, locator, parsingMode); List statements = parser.parseFileInput(); - return new ParseResult(statements, parser.comments, - parser.errorsCount > 0 || lexer.containsErrors()); + return new ParseResult( + statements, parser.comments, parser.errorsCount > 0 || lexer.containsErrors()); } /** @@ -188,9 +200,11 @@ class Parser { * that are not part of the core BUILD language. */ public static ParseResult parseFileForSkylark( - Lexer lexer, EventHandler eventHandler, CachingPackageLocator locator, + Lexer lexer, + EventHandler eventHandler, + CachingPackageLocator locator, ValidationEnvironment validationEnvironment) { - Parser parser = new Parser(lexer, eventHandler, locator).setSkylarkMode(true); + Parser parser = new Parser(lexer, eventHandler, locator, SKYLARK); List statements = parser.parseFileInput(); boolean hasSemanticalErrors = false; try { @@ -328,7 +342,7 @@ class Parser { TokenKind.TRY, TokenKind.WITH, TokenKind.WHILE, TokenKind.YIELD); private void checkForbiddenKeywords(Token token) { - if (parsePython || !FORBIDDEN_KEYWORDS.contains(token.kind)) { + if (parsingMode == PYTHON || !FORBIDDEN_KEYWORDS.contains(token.kind)) { return; } String error; @@ -415,7 +429,7 @@ class Parser { final int start = token.left; // parse **expr if (token.kind == TokenKind.STAR_STAR) { - if (!skylarkMode) { + if (parsingMode != SKYLARK) { reportError( lexer.createLocation(token.left, token.right), "**kwargs arguments are not allowed in BUILD files"); @@ -426,7 +440,7 @@ class Parser { } // parse *expr if (token.kind == TokenKind.STAR) { - if (!skylarkMode) { + if (parsingMode != SKYLARK) { reportError( lexer.createLocation(token.left, token.right), "*args arguments are not allowed in BUILD files"); @@ -617,8 +631,8 @@ class Parser { // Insert call to the mocksubinclude function to get the dependencies right. list.add(mocksubincludeExpression(labelName, file.toString(), location)); - Lexer lexer = new Lexer(inputSource, eventHandler, parsePython); - Parser parser = new Parser(lexer, eventHandler, locator, parsePython); + Lexer lexer = new Lexer(inputSource, eventHandler, parsingMode == PYTHON); + Parser parser = new Parser(lexer, eventHandler, locator, parsingMode); parser.addIncludedFiles(this.includedFiles); list.addAll(parser.parseFileInput()); } catch (Label.SyntaxException e) { @@ -1092,7 +1106,9 @@ class Parser { Token identToken = token; Ident ident = parseIdent(); - if (ident.getName().equals("include") && token.kind == TokenKind.LPAREN && !skylarkMode) { + if (ident.getName().equals("include") + && token.kind == TokenKind.LPAREN + && parsingMode == BUILD) { expect(TokenKind.LPAREN); if (token.kind == TokenKind.STRING) { include((String) token.value, list, lexer.createLocation(start, token.right)); @@ -1366,15 +1382,15 @@ class Parser { // stmt ::= simple_stmt // | compound_stmt private void parseStatement(List list, boolean isTopLevel) { - if (token.kind == TokenKind.DEF && skylarkMode) { + if (token.kind == TokenKind.DEF && parsingMode == SKYLARK) { if (!isTopLevel) { reportError(lexer.createLocation(token.left, token.right), "nested functions are not allowed. Move the function to top-level"); } parseFunctionDefStatement(list); - } else if (token.kind == TokenKind.IF && skylarkMode) { + } else if (token.kind == TokenKind.IF && parsingMode == SKYLARK) { list.add(parseIfStatement()); - } else if (token.kind == TokenKind.FOR && skylarkMode) { + } else if (token.kind == TokenKind.FOR && parsingMode == SKYLARK) { if (isTopLevel) { reportError(lexer.createLocation(token.left, token.right), "for loops are not allowed on top-level. Put it into a function"); @@ -1405,7 +1421,7 @@ class Parser { int start = token.left; Token blockToken = token; syncTo(EnumSet.of(TokenKind.COLON, TokenKind.EOF)); // skip over expression or name - if (!parsePython) { + if (parsingMode == BUILD) { reportError(lexer.createLocation(start, token.right), "syntax error at '" + blockToken + "': This Python-style construct is not supported. " + Constants.PARSER_ERROR_EXTENSION_NEEDED); -- cgit v1.2.3