| 1909 | |
| 1910 | |
| 1911 | void Parser::ParseArrayInitializer(Declaration* decl, |
| 1912 | ArrayType* type, |
| 1913 | int offset, |
| 1914 | bool designated) { |
| 1915 | assert(type); |
| 1916 | |
| 1917 | if (!type->Complete()) |
| 1918 | type->SetLen(0); |
| 1919 | |
| 1920 | int idx = 0; |
| 1921 | auto width = type->Derived()->Width(); |
| 1922 | auto hasBrace = ts_.Try('{'); |
| 1923 | while (true) { |
| 1924 | if (ts_.Test('}')) { |
| 1925 | if (hasBrace) |
| 1926 | ts_.Next(); |
| 1927 | return; |
| 1928 | } |
| 1929 | |
| 1930 | if (!designated && !hasBrace && (ts_.Test('.') || ts_.Test('['))) { |
| 1931 | ts_.PutBack(); // Put the read comma(',') back |
| 1932 | return; |
| 1933 | } else if ((designated = ts_.Try('['))) { |
| 1934 | auto expr = ParseAssignExpr(); |
| 1935 | EnsureInteger(expr); |
| 1936 | idx = Evaluator<long>().Eval(expr); |
| 1937 | ts_.Expect(']'); |
| 1938 | |
| 1939 | if (idx < 0 || (type->Complete() && idx >= type->Len())) { |
| 1940 | Error(ts_.Peek(), "excess elements in array initializer"); |
| 1941 | } |
| 1942 | } |
| 1943 | |
| 1944 | ParseInitializer(decl, type->Derived(), offset + idx * width, designated); |
| 1945 | designated = false; |
| 1946 | ++idx; |
| 1947 | |
| 1948 | if (type->Complete() && idx >= type->Len()) { |
| 1949 | break; |
| 1950 | } else if (!type->Complete()) { |
| 1951 | type->SetLen(std::max(idx, type->Len())); |
| 1952 | } |
| 1953 | |
| 1954 | // Needless comma at the end is legal |
| 1955 | if (!ts_.Try(',')) { |
| 1956 | if (hasBrace) |
| 1957 | ts_.Expect('}'); |
| 1958 | return; |
| 1959 | } |
| 1960 | } |
| 1961 | |
| 1962 | if (hasBrace) { |
| 1963 | ts_.Try(','); |
| 1964 | if (!ts_.Try('}')) { |
| 1965 | Error(ts_.Peek(), "excess elements in array initializer"); |
| 1966 | } |
| 1967 | } |
| 1968 | } |