| 4987 | } |
| 4988 | |
| 4989 | void parser:: |
| 4990 | parse_export (token& t, type& tt) |
| 4991 | { |
| 4992 | tracer trace ("parser::parse_export", &path_); |
| 4993 | |
| 4994 | // This should be temp_scope for export. |
| 4995 | // |
| 4996 | if (scope_->role_ != scope::role::temp_export) |
| 4997 | fail (t) << "export outside export stub"; |
| 4998 | |
| 4999 | // The rest is a value. Parse it similar to a value on the RHS of an |
| 5000 | // assignment to get expansion. While it may seem like supporting |
| 5001 | // attributes is a good idea here, there is actually little benefit in |
| 5002 | // being able to type them or to return NULL. |
| 5003 | // |
| 5004 | mode (lexer_mode::value, '@'); |
| 5005 | next_with_attributes (t, tt); |
| 5006 | |
| 5007 | auto at (attributes_push (t, tt)); |
| 5008 | |
| 5009 | if (at.first) |
| 5010 | fail (at.second) << "attributes in export"; |
| 5011 | else |
| 5012 | attributes_pop (); |
| 5013 | |
| 5014 | location l (get_location (t)); |
| 5015 | value val (tt != type::newline && tt != type::eos |
| 5016 | ? parse_value (t, tt, pattern_mode::expand) |
| 5017 | : value (names ())); |
| 5018 | |
| 5019 | if (!val) |
| 5020 | fail (l) << "null value in export"; |
| 5021 | |
| 5022 | if (val.type != nullptr) |
| 5023 | { |
| 5024 | // While feels far-fetched, let's preserve empty typed values in the |
| 5025 | // result. |
| 5026 | // |
| 5027 | untypify (val, false /* reduce */); |
| 5028 | } |
| 5029 | |
| 5030 | export_value = move (val).as<names> (); |
| 5031 | |
| 5032 | if (export_value.empty ()) |
| 5033 | fail (l) << "empty value in export"; |
| 5034 | |
| 5035 | next_after_newline (t, tt); |
| 5036 | } |
| 5037 | |
| 5038 | void parser:: |
| 5039 | parse_using (token& t, type& tt) |
nothing calls this directly
no test coverage detected