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 |