| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "tools/gn/parser.h" | 5 #include "tools/gn/parser.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 11 #include "tools/gn/functions.h" | 11 #include "tools/gn/functions.h" |
| 12 #include "tools/gn/operators.h" | 12 #include "tools/gn/operators.h" |
| 13 #include "tools/gn/token.h" | 13 #include "tools/gn/token.h" |
| 14 | 14 |
| 15 const char kGrammar_Help[] = | 15 const char kGrammar_Help[] = |
| 16 "Language and grammar for GN build files\n" | 16 R"*(Language and grammar for GN build files |
| 17 "\n" | 17 |
| 18 "Tokens\n" | 18 Tokens |
| 19 "\n" | 19 |
| 20 " GN build files are read as sequences of tokens. While splitting the\n" | 20 GN build files are read as sequences of tokens. While splitting the file |
| 21 " file into tokens, the next token is the longest sequence of characters\n" | 21 into tokens, the next token is the longest sequence of characters that form a |
| 22 " that form a valid token.\n" | 22 valid token. |
| 23 "\n" | 23 |
| 24 "White space and comments\n" | 24 White space and comments |
| 25 "\n" | 25 |
| 26 " White space is comprised of spaces (U+0020), horizontal tabs (U+0009),\n" | 26 White space is comprised of spaces (U+0020), horizontal tabs (U+0009), |
| 27 " carriage returns (U+000D), and newlines (U+000A).\n" | 27 carriage returns (U+000D), and newlines (U+000A). |
| 28 "\n" | 28 |
| 29 " Comments start at the character \"#\" and stop at the next newline.\n" | 29 Comments start at the character "#" and stop at the next newline. |
| 30 "\n" | 30 |
| 31 " White space and comments are ignored except that they may separate\n" | 31 White space and comments are ignored except that they may separate tokens |
| 32 " tokens that would otherwise combine into a single token.\n" | 32 that would otherwise combine into a single token. |
| 33 "\n" | 33 |
| 34 "Identifiers\n" | 34 Identifiers |
| 35 "\n" | 35 |
| 36 " Identifiers name variables and functions.\n" | 36 Identifiers name variables and functions. |
| 37 "\n" | 37 |
| 38 " identifier = letter { letter | digit } .\n" | 38 identifier = letter { letter | digit } . |
| 39 " letter = \"A\" ... \"Z\" | \"a\" ... \"z\" | \"_\" .\n" | 39 letter = "A" ... "Z" | "a" ... "z" | "_" . |
| 40 " digit = \"0\" ... \"9\" .\n" | 40 digit = "0" ... "9" . |
| 41 "\n" | 41 |
| 42 "Keywords\n" | 42 Keywords |
| 43 "\n" | 43 |
| 44 " The following keywords are reserved and may not be used as\n" | 44 The following keywords are reserved and may not be used as identifiers: |
| 45 " identifiers:\n" | 45 |
| 46 "\n" | 46 else false if true |
| 47 " else false if true\n" | 47 |
| 48 "\n" | 48 Integer literals |
| 49 "Integer literals\n" | 49 |
| 50 "\n" | 50 An integer literal represents a decimal integer value. |
| 51 " An integer literal represents a decimal integer value.\n" | 51 |
| 52 "\n" | 52 integer = [ "-" ] digit { digit } . |
| 53 " integer = [ \"-\" ] digit { digit } .\n" | 53 |
| 54 "\n" | 54 Leading zeros and negative zero are disallowed. |
| 55 " Leading zeros and negative zero are disallowed.\n" | 55 |
| 56 "\n" | 56 String literals |
| 57 "String literals\n" | 57 |
| 58 "\n" | 58 A string literal represents a string value consisting of the quoted |
| 59 " A string literal represents a string value consisting of the quoted\n" | 59 characters with possible escape sequences and variable expansions. |
| 60 " characters with possible escape sequences and variable expansions.\n" | 60 |
| 61 "\n" | 61 string = `"` { char | escape | expansion } `"` . |
| 62 " string = `\"` { char | escape | expansion } `\"` .\n" | 62 escape = `\` ( "$" | `"` | char ) . |
| 63 " escape = `\\` ( \"$\" | `\"` | char ) .\n" | 63 BracketExpansion = "{" ( identifier | ArrayAccess | ScopeAccess " |
| 64 " BracketExpansion = \"{\" ( identifier | ArrayAccess | ScopeAccess " | 64 ") "}" . |
| 65 ") \"}\" .\n" | 65 Hex = "0x" [0-9A-Fa-f][0-9A-Fa-f] |
| 66 " Hex = \"0x\" [0-9A-Fa-f][0-9A-Fa-f]\n" | 66 expansion = "$" ( identifier | BracketExpansion | Hex ) . |
| 67 " expansion = \"$\" ( identifier | BracketExpansion | Hex ) .\n" | 67 char = /* any character except "$", `"`, or newline " |
| 68 " char = /* any character except \"$\", `\"`, or newline " | 68 "*/ . |
| 69 "*/ .\n" | 69 |
| 70 "\n" | 70 After a backslash, certain sequences represent special characters: |
| 71 " After a backslash, certain sequences represent special characters:\n" | 71 |
| 72 "\n" | 72 \" U+0022 quotation mark |
| 73 " \\\" U+0022 quotation mark\n" | 73 \$ U+0024 dollar sign |
| 74 " \\$ U+0024 dollar sign\n" | 74 \\ U+005C backslash |
| 75 " \\\\ U+005C backslash\n" | 75 |
| 76 "\n" | 76 All other backslashes represent themselves. |
| 77 " All other backslashes represent themselves.\n" | 77 |
| 78 "\n" | 78 To insert an arbitrary byte value, use $0xFF. For example, to insert a |
| 79 " To insert an arbitrary byte value, use $0xFF. For example, to\n" | 79 newline character: "Line one$0x0ALine two". |
| 80 " insert a newline character: \"Line one$0x0ALine two\".\n" | 80 |
| 81 "\n" | 81 An expansion will evaluate the variable following the '$' and insert a |
| 82 " An expansion will evaluate the variable following the '$' and insert\n" | 82 stringified version of it into the result. For example, to concat two path |
| 83 " a stringified version of it into the result. For example, to concat\n" | 83 components with a slash separating them: |
| 84 " two path components with a slash separating them:\n" | 84 "$var_one/$var_two" |
| 85 " \"$var_one/$var_two\"\n" | 85 Use the "${var_one}" format to be explicitly deliniate the variable for |
| 86 " Use the \"${var_one}\" format to be explicitly deliniate the variable\n" | 86 otherwise-ambiguous cases. |
| 87 " for otherwise-ambiguous cases.\n" | 87 |
| 88 "\n" | 88 Punctuation |
| 89 "Punctuation\n" | 89 |
| 90 "\n" | 90 The following character sequences represent punctuation: |
| 91 " The following character sequences represent punctuation:\n" | 91 |
| 92 "\n" | 92 + += == != ( ) |
| 93 " + += == != ( )\n" | 93 - -= < <= [ ] |
| 94 " - -= < <= [ ]\n" | 94 ! = > >= { } |
| 95 " ! = > >= { }\n" | 95 && || . , |
| 96 " && || . ,\n" | 96 |
| 97 "\n" | 97 Grammar |
| 98 "Grammar\n" | 98 |
| 99 "\n" | 99 The input tokens form a syntax tree following a context-free grammar: |
| 100 " The input tokens form a syntax tree following a context-free grammar:\n" | 100 |
| 101 "\n" | 101 File = StatementList . |
| 102 " File = StatementList .\n" | 102 |
| 103 "\n" | 103 Statement = Assignment | Call | Condition . |
| 104 " Statement = Assignment | Call | Condition .\n" | 104 LValue = identifier | ArrayAccess | ScopeAccess . |
| 105 " LValue = identifier | ArrayAccess | ScopeAccess .\n" | 105 Assignment = LValue AssignOp Expr . |
| 106 " Assignment = LValue AssignOp Expr .\n" | 106 Call = identifier "(" [ ExprList ] ")" [ Block ] . |
| 107 " Call = identifier \"(\" [ ExprList ] \")\" [ Block ] .\n" | 107 Condition = "if" "(" Expr ")" Block |
| 108 " Condition = \"if\" \"(\" Expr \")\" Block\n" | 108 [ "else" ( Condition | Block ) ] . |
| 109 " [ \"else\" ( Condition | Block ) ] .\n" | 109 Block = "{" StatementList "}" . |
| 110 " Block = \"{\" StatementList \"}\" .\n" | 110 StatementList = { Statement } . |
| 111 " StatementList = { Statement } .\n" | 111 |
| 112 "\n" | 112 ArrayAccess = identifier "[" Expr "]" . |
| 113 " ArrayAccess = identifier \"[\" Expr \"]\" .\n" | 113 ScopeAccess = identifier "." identifier . |
| 114 " ScopeAccess = identifier \".\" identifier .\n" | 114 Expr = UnaryExpr | Expr BinaryOp Expr . |
| 115 " Expr = UnaryExpr | Expr BinaryOp Expr .\n" | 115 UnaryExpr = PrimaryExpr | UnaryOp UnaryExpr . |
| 116 " UnaryExpr = PrimaryExpr | UnaryOp UnaryExpr .\n" | 116 PrimaryExpr = identifier | integer | string | Call |
| 117 " PrimaryExpr = identifier | integer | string | Call\n" | 117 | ArrayAccess | ScopeAccess | Block |
| 118 " | ArrayAccess | ScopeAccess | Block\n" | 118 | "(" Expr ")" |
| 119 " | \"(\" Expr \")\"\n" | 119 | "[" [ ExprList [ "," ] ] "]" . |
| 120 " | \"[\" [ ExprList [ \",\" ] ] \"]\" .\n" | 120 ExprList = Expr { "," Expr } . |
| 121 " ExprList = Expr { \",\" Expr } .\n" | 121 |
| 122 "\n" | 122 AssignOp = "=" | "+=" | "-=" . |
| 123 " AssignOp = \"=\" | \"+=\" | \"-=\" .\n" | 123 UnaryOp = "!" . |
| 124 " UnaryOp = \"!\" .\n" | 124 BinaryOp = "+" | "-" // highest priority |
| 125 " BinaryOp = \"+\" | \"-\" // highest priority\n" | 125 | "<" | "<=" | ">" | ">=" |
| 126 " | \"<\" | \"<=\" | \">\" | \">=\"\n" | 126 | "==" | "!=" |
| 127 " | \"==\" | \"!=\"\n" | 127 | "&&" |
| 128 " | \"&&\"\n" | 128 | "||" . // lowest priority |
| 129 " | \"||\" . // lowest priority\n" | 129 |
| 130 "\n" | 130 All binary operators are left-associative. |
| 131 " All binary operators are left-associative.\n" | 131 |
| 132 "\n" | 132 Types |
| 133 "Types\n" | 133 |
| 134 "\n" | 134 The GN language is dynamically typed. The following types are used: |
| 135 " The GN language is dynamically typed. The following types are used:\n" | 135 |
| 136 "\n" | 136 - Boolean: Uses the keywords "true" and "false". There is no implicit |
| 137 " - Boolean: Uses the keywords \"true\" and \"false\". There is no\n" | 137 conversion between booleans and integers. |
| 138 " implicit conversion between booleans and integers.\n" | 138 |
| 139 "\n" | 139 - Integers: All numbers in GN are signed 64-bit integers. |
| 140 " - Integers: All numbers in GN are signed 64-bit integers.\n" | 140 |
| 141 "\n" | 141 - Strings: Strings are 8-bit with no enforced encoding. When a string is |
| 142 " - Strings: Strings are 8-bit with no enforced encoding. When a string\n" | 142 used to interact with other systems with particular encodings (like the |
| 143 " is used to interact with other systems with particular encodings\n" | 143 Windows and Mac filesystems) it is assumed to be UTF-8. See "String |
| 144 " (like the Windows and Mac filesystems) it is assumed to be UTF-8.\n" | 144 literals" above for more. |
| 145 " See \"String literals\" above for more.\n" | 145 |
| 146 "\n" | 146 - Lists: Lists are arbitrary-length ordered lists of values. See "Lists" |
| 147 " - Lists: Lists are arbitrary-length ordered lists of values. See\n" | 147 below for more. |
| 148 " \"Lists\" below for more.\n" | 148 |
| 149 "\n" | 149 - Scopes: Scopes are like dictionaries that use variable names for keys. See |
| 150 " - Scopes: Scopes are like dictionaries that use variable names for\n" | 150 "Scopes" below for more. |
| 151 " keys. See \"Scopes\" below for more.\n" | 151 |
| 152 "\n" | 152 Lists |
| 153 "Lists\n" | 153 |
| 154 "\n" | 154 Lists are created with [] and using commas to separate items: |
| 155 " Lists are created with [] and using commas to separate items:\n" | 155 |
| 156 "\n" | 156 mylist = [ 0, 1, 2, "some string" ] |
| 157 " mylist = [ 0, 1, 2, \"some string\" ]\n" | 157 |
| 158 "\n" | 158 A comma after the last item is optional. Lists are dereferenced using 0-based |
| 159 " A comma after the last item is optional. Lists are dereferenced using\n" | 159 indexing: |
| 160 " 0-based indexing:\n" | 160 |
| 161 "\n" | 161 mylist[0] += 1 |
| 162 " mylist[0] += 1\n" | 162 var = mylist[2] |
| 163 " var = mylist[2]\n" | 163 |
| 164 "\n" | 164 Lists can be concatenated using the '+' and '+=' operators. Bare values can |
| 165 " Lists can be concatenated using the '+' and '+=' operators. Bare\n" | 165 not be concatenated with lists, to add a single item, it must be put into a |
| 166 " values can not be concatenated with lists, to add a single item,\n" | 166 list of length one. |
| 167 " it must be put into a list of length one.\n" | 167 |
| 168 "\n" | 168 Items can be removed from lists using the '-' and '-=' operators. This will |
| 169 " Items can be removed from lists using the '-' and '-=' operators.\n" | 169 remove all occurrences of every item in the right-hand list from the |
| 170 " This will remove all occurrences of every item in the right-hand list\n" | 170 left-hand list. It is an error to remove an item not in the list. This is to |
| 171 " from the left-hand list. It is an error to remove an item not in the\n" | 171 prevent common typos and to detect dead code that is removing things that no |
| 172 " list. This is to prevent common typos and to detect dead code that\n" | 172 longer apply. |
| 173 " is removing things that no longer apply.\n" | 173 |
| 174 "\n" | 174 It is an error to use '=' to replace a nonempty list with another nonempty |
| 175 " It is an error to use '=' to replace a nonempty list with another\n" | 175 list. This is to prevent accidentally overwriting data when in most cases |
| 176 " nonempty list. This is to prevent accidentally overwriting data\n" | 176 '+=' was intended. To overwrite a list on purpose, first assign it to the |
| 177 " when in most cases '+=' was intended. To overwrite a list on purpose,\n" | 177 empty list: |
| 178 " first assign it to the empty list:\n" | 178 |
| 179 "\n" | 179 mylist = [] |
| 180 " mylist = []\n" | 180 mylist = otherlist |
| 181 " mylist = otherlist\n" | 181 |
| 182 "\n" | 182 When assigning to a list named 'sources' using '=' or '+=', list items may be |
| 183 " When assigning to a list named 'sources' using '=' or '+=', list\n" | 183 automatically filtered out. See "gn help set_sources_assignment_filter" for |
| 184 " items may be automatically filtered out.\n" | 184 more. |
| 185 " See \"gn help set_sources_assignment_filter\" for more.\n" | 185 |
| 186 "\n" | 186 Scopes |
| 187 "Scopes\n" | 187 |
| 188 "\n" | 188 All execution happens in the context of a scope which holds the current state |
| 189 " All execution happens in the context of a scope which holds the\n" | 189 (like variables). With the exception of loops and conditions, '{' introduces |
| 190 " current state (like variables). With the exception of loops and\n" | 190 a new scope that has a parent reference to the old scope. |
| 191 " conditions, '{' introduces a new scope that has a parent reference to\n" | 191 |
| 192 " the old scope.\n" | 192 Variable reads recursively search all nested scopes until the variable is |
| 193 "\n" | 193 found or there are no more scopes. Variable writes always go into the current |
| 194 " Variable reads recursively search all nested scopes until the\n" | 194 scope. This means that after the closing '}' (again excepting loops and |
| 195 " variable is found or there are no more scopes. Variable writes always\n" | 195 conditions), all local variables will be restored to the previous values. |
| 196 " go into the current scope. This means that after the closing '}'\n" | 196 This also means that "foo = foo" can do useful work by copying a variable |
| 197 " (again excepting loops and conditions), all local variables will be\n" | 197 into the current scope that was defined in a containing scope. |
| 198 " restored to the previous values. This also means that \"foo = foo\"\n" | 198 |
| 199 " can do useful work by copying a variable into the current scope that\n" | 199 Scopes can also be assigned to variables. Such scopes can be created by |
| 200 " was defined in a containing scope.\n" | 200 functions like exec_script, when invoking a template (the template code |
| 201 "\n" | 201 refers to the variables set by the invoking code by the implicitly-created |
| 202 " Scopes can also be assigned to variables. Such scopes can be created\n" | 202 "invoker" scope), or explicitly like: |
| 203 " by functions like exec_script, when invoking a template (the template\n" | 203 |
| 204 " code refers to the variables set by the invoking code by the\n" | 204 empty_scope = {} |
| 205 " implicitly-created \"invoker\" scope), or explicitly like:\n" | 205 myvalues = { |
| 206 "\n" | 206 foo = 21 |
| 207 " empty_scope = {}\n" | 207 bar = "something" |
| 208 " myvalues = {\n" | 208 } |
| 209 " foo = 21\n" | 209 |
| 210 " bar = \"something\"\n" | 210 Inside such a scope definition can be any GN code including conditionals and |
| 211 " }\n" | 211 function calls. After the close of the scope, it will contain all variables |
| 212 "\n" | 212 explicitly set by the code contained inside it. After this, the values can be |
| 213 " Inside such a scope definition can be any GN code including\n" | 213 read, modified, or added to: |
| 214 " conditionals and function calls. After the close of the scope, it will\n" | 214 |
| 215 " contain all variables explicitly set by the code contained inside it.\n" | 215 myvalues.foo += 2 |
| 216 " After this, the values can be read, modified, or added to:\n" | 216 empty_scope.new_thing = [ 1, 2, 3 ] |
| 217 "\n" | 217 )*"; |
| 218 " myvalues.foo += 2\n" | |
| 219 " empty_scope.new_thing = [ 1, 2, 3 ]\n"; | |
| 220 | 218 |
| 221 enum Precedence { | 219 enum Precedence { |
| 222 PRECEDENCE_ASSIGNMENT = 1, // Lowest precedence. | 220 PRECEDENCE_ASSIGNMENT = 1, // Lowest precedence. |
| 223 PRECEDENCE_OR = 2, | 221 PRECEDENCE_OR = 2, |
| 224 PRECEDENCE_AND = 3, | 222 PRECEDENCE_AND = 3, |
| 225 PRECEDENCE_EQUALITY = 4, | 223 PRECEDENCE_EQUALITY = 4, |
| 226 PRECEDENCE_RELATION = 5, | 224 PRECEDENCE_RELATION = 5, |
| 227 PRECEDENCE_SUM = 6, | 225 PRECEDENCE_SUM = 6, |
| 228 PRECEDENCE_PREFIX = 7, | 226 PRECEDENCE_PREFIX = 7, |
| 229 PRECEDENCE_CALL = 8, | 227 PRECEDENCE_CALL = 8, |
| (...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 break; | 873 break; |
| 876 } | 874 } |
| 877 } | 875 } |
| 878 | 876 |
| 879 // Suffix comments were assigned in reverse, so if there were multiple on | 877 // Suffix comments were assigned in reverse, so if there were multiple on |
| 880 // the same node, they need to be reversed. | 878 // the same node, they need to be reversed. |
| 881 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) | 879 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) |
| 882 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); | 880 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); |
| 883 } | 881 } |
| 884 } | 882 } |
| OLD | NEW |