Mercurial > projects > dil
comparison trunk/src/dil/Parser.d @ 483:180711cc4b66
Fixed parsing of C-style function pointers.
Renamed some labels. Added calls to set().
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Sun, 25 Nov 2007 20:48:10 +0100 |
parents | cac9c8d637ad |
children | 265c0b655f18 |
comparison
equal
deleted
inserted
replaced
482:1401e38d1e2e | 483:180711cc4b66 |
---|---|
321 nT(); | 321 nT(); |
322 decl = new EmptyDeclaration(); | 322 decl = new EmptyDeclaration(); |
323 break; | 323 break; |
324 // Declaration | 324 // Declaration |
325 case T.Identifier, T.Dot, T.Typeof: | 325 case T.Identifier, T.Dot, T.Typeof: |
326 // BasicType | 326 // IntegralType |
327 case T.Char, T.Wchar, T.Dchar, T.Bool, | 327 case T.Char, T.Wchar, T.Dchar, T.Bool, |
328 T.Byte, T.Ubyte, T.Short, T.Ushort, | 328 T.Byte, T.Ubyte, T.Short, T.Ushort, |
329 T.Int, T.Uint, T.Long, T.Ulong, | 329 T.Int, T.Uint, T.Long, T.Ulong, |
330 T.Float, T.Double, T.Real, | 330 T.Float, T.Double, T.Real, |
331 T.Ifloat, T.Idouble, T.Ireal, | 331 T.Ifloat, T.Idouble, T.Ireal, |
332 T.Cfloat, T.Cdouble, T.Creal, T.Void: | 332 T.Cfloat, T.Cdouble, T.Creal, T.Void: |
333 case_Declaration: | 333 case_Declaration: |
334 decl = parseDeclaration(); | 334 return parseDeclaration(); |
335 break; | |
336 /+case T.Module: | 335 /+case T.Module: |
337 // TODO: Error: module is optional and can appear only once at the top of the source file. | 336 // TODO: Error: module is optional and can appear only once at the top of the source file. |
338 break;+/ | 337 break;+/ |
339 default: | 338 default: |
340 error(MID.ExpectedButFound, "Declaration", token.srcText); | 339 error(MID.ExpectedButFound, "Declaration", token.srcText); |
378 Declaration parseDeclarationsBlockNoColon() | 377 Declaration parseDeclarationsBlockNoColon() |
379 { | 378 { |
380 return parseDeclarationsBlock(true); | 379 return parseDeclarationsBlock(true); |
381 } | 380 } |
382 | 381 |
383 Declaration parseDeclaration(StorageClass stc = StorageClass.None) | 382 /++ |
384 { | 383 Parses either a VariableDeclaration or a FunctionDeclaration. |
384 Params: | |
385 stc = the previously parsed storage classes | |
386 optionalParameterList = a hint for how to parse C-style function pointers | |
387 +/ | |
388 Declaration parseDeclaration(StorageClass stc = StorageClass.None, bool optionalParameterList = true) | |
389 { | |
390 auto begin = token; | |
385 Type type; | 391 Type type; |
386 Token* ident; | 392 Token* ident; |
387 | 393 |
388 // Check for AutoDeclaration | 394 // Check for AutoDeclaration |
389 if (stc != StorageClass.None && | 395 if (stc != StorageClass.None && |
396 else | 402 else |
397 { | 403 { |
398 type = parseType(); | 404 type = parseType(); |
399 if (token.type == T.LParen) | 405 if (token.type == T.LParen) |
400 { | 406 { |
401 parseCFunctionPointerType(type, ident); | 407 // C-style function pointers make the grammar ambiguous. |
408 // We have to treat them specially at function scope. | |
409 // Example: | |
410 // void foo() { | |
411 // // A pointer to a function taking an integer and returning 'some_type'. | |
412 // some_type (*p_func)(int); | |
413 // // In the following case precedence is given to a CallExpression. | |
414 // something(*p); // 'something' may be a function/method or an object having opCall overloaded. | |
415 // } | |
416 // // A pointer to a function taking no parameters and returning 'something'. | |
417 // something(*p); | |
418 type = parseCFunctionPointerType(type, ident, optionalParameterList); | |
402 } | 419 } |
403 else | 420 else |
404 { | 421 { |
405 ident = requireId(); | 422 ident = requireId(); |
406 // Type FunctionName ( ParameterList ) FunctionBody | 423 // Type FunctionName ( ParameterList ) FunctionBody |
415 } | 432 } |
416 | 433 |
417 auto params = parseParameterList(); | 434 auto params = parseParameterList(); |
418 // ReturnType FunctionName ( ParameterList ) | 435 // ReturnType FunctionName ( ParameterList ) |
419 auto funcBody = parseFunctionBody(); | 436 auto funcBody = parseFunctionBody(); |
420 return new FunctionDeclaration(type, ident, tparams, params, funcBody); | 437 return set(new FunctionDeclaration(type, ident, tparams, params, funcBody), begin); |
421 } | 438 } |
422 type = parseDeclaratorSuffix(type); | 439 type = parseDeclaratorSuffix(type); |
423 } | 440 } |
424 } | 441 } |
425 | 442 |
439 } | 456 } |
440 else | 457 else |
441 values ~= null; | 458 values ~= null; |
442 } | 459 } |
443 require(T.Semicolon); | 460 require(T.Semicolon); |
444 return new VariableDeclaration(type, idents, values); | 461 return set(new VariableDeclaration(type, idents, values), begin); |
445 } | 462 } |
446 | 463 |
447 Expression parseInitializer() | 464 Expression parseInitializer() |
448 { | 465 { |
449 if (token.type == T.Void) | 466 if (token.type == T.Void) |
1603 if (token.type == T.Struct) | 1620 if (token.type == T.Struct) |
1604 structDecl = parseAggregateDeclaration(); | 1621 structDecl = parseAggregateDeclaration(); |
1605 else | 1622 else |
1606 expected(T.Struct); | 1623 expected(T.Struct); |
1607 d = new AlignDeclaration(size, structDecl ? structDecl : new Declarations); | 1624 d = new AlignDeclaration(size, structDecl ? structDecl : new Declarations); |
1608 goto case_DeclarationStatement; | 1625 goto LreturnDeclarationStatement; |
1609 /+ Not applicable for statements. | 1626 /+ Not applicable for statements. |
1610 // T.Private, | 1627 // T.Private, |
1611 // T.Package, | 1628 // T.Package, |
1612 // T.Protected, | 1629 // T.Protected, |
1613 // T.Public, | 1630 // T.Public, |
1635 break; | 1652 break; |
1636 } | 1653 } |
1637 goto case T.Dot; | 1654 goto case T.Dot; |
1638 case T.Dot, T.Typeof: | 1655 case T.Dot, T.Typeof: |
1639 bool success; | 1656 bool success; |
1640 d = try_({return parseDeclaration();}, success); | 1657 d = try_({return parseDeclaration(StorageClass.None, false);}, success); |
1641 if (success) | 1658 if (success) |
1642 goto case_DeclarationStatement; // Declaration | 1659 goto LreturnDeclarationStatement; // Declaration |
1643 else | 1660 else |
1644 goto case_ExpressionStatement; // Expression | 1661 goto case_parseExpressionStatement; // Expression |
1645 // BasicType | 1662 // IntegralType |
1646 case T.Char, T.Wchar, T.Dchar, T.Bool, | 1663 case T.Char, T.Wchar, T.Dchar, T.Bool, |
1647 T.Byte, T.Ubyte, T.Short, T.Ushort, | 1664 T.Byte, T.Ubyte, T.Short, T.Ushort, |
1648 T.Int, T.Uint, T.Long, T.Ulong, | 1665 T.Int, T.Uint, T.Long, T.Ulong, |
1649 T.Float, T.Double, T.Real, | 1666 T.Float, T.Double, T.Real, |
1650 T.Ifloat, T.Idouble, T.Ireal, | 1667 T.Ifloat, T.Idouble, T.Ireal, |
1651 T.Cfloat, T.Cdouble, T.Creal, T.Void: | 1668 T.Cfloat, T.Cdouble, T.Creal, T.Void: |
1652 case_parseDeclaration: | 1669 case_parseDeclaration: |
1653 d = parseDeclaration(); | 1670 d = parseDeclaration(); |
1654 goto case_DeclarationStatement; | 1671 goto LreturnDeclarationStatement; |
1655 case T.If: | 1672 case T.If: |
1656 s = parseIfStatement(); | 1673 s = parseIfStatement(); |
1657 break; | 1674 break; |
1658 case T.While: | 1675 case T.While: |
1659 s = parseWhileStatement(); | 1676 s = parseWhileStatement(); |
1714 case T.Pragma: | 1731 case T.Pragma: |
1715 s = parsePragmaStatement(); | 1732 s = parsePragmaStatement(); |
1716 break; | 1733 break; |
1717 case T.Mixin: | 1734 case T.Mixin: |
1718 if (peekNext() == T.LParen) | 1735 if (peekNext() == T.LParen) |
1719 goto case_ExpressionStatement; // Parse as expression. | 1736 goto case_parseExpressionStatement; // Parse as expression. |
1720 s = parseMixin!(MixinStatement)(); | 1737 s = parseMixin!(MixinStatement)(); |
1721 break; | 1738 break; |
1722 case T.Static: | 1739 case T.Static: |
1723 switch (peekNext()) | 1740 switch (peekNext()) |
1724 { | 1741 { |
1739 s = parseVersionStatement(); | 1756 s = parseVersionStatement(); |
1740 break; | 1757 break; |
1741 // DeclDef | 1758 // DeclDef |
1742 case T.Alias, T.Typedef: | 1759 case T.Alias, T.Typedef: |
1743 d = parseDeclarationDefinition(); | 1760 d = parseDeclarationDefinition(); |
1744 goto case_DeclarationStatement; | 1761 goto LreturnDeclarationStatement; |
1745 case T.Enum: | 1762 case T.Enum: |
1746 d = parseEnumDeclaration(); | 1763 d = parseEnumDeclaration(); |
1747 goto case_DeclarationStatement; | 1764 goto LreturnDeclarationStatement; |
1748 case T.Class: | 1765 case T.Class: |
1749 d = parseClassDeclaration(); | 1766 d = parseClassDeclaration(); |
1750 goto case_DeclarationStatement; | 1767 goto LreturnDeclarationStatement; |
1751 case T.Interface: | 1768 case T.Interface: |
1752 d = parseInterfaceDeclaration(); | 1769 d = parseInterfaceDeclaration(); |
1753 goto case_DeclarationStatement; | 1770 goto LreturnDeclarationStatement; |
1754 case T.Struct, T.Union: | 1771 case T.Struct, T.Union: |
1755 d = parseAggregateDeclaration(); | 1772 d = parseAggregateDeclaration(); |
1756 goto case_DeclarationStatement; | 1773 // goto LreturnDeclarationStatement; |
1757 case_DeclarationStatement: | 1774 LreturnDeclarationStatement: |
1758 set(d, begin); | 1775 set(d, begin); |
1759 s = new DeclarationStatement(d); | 1776 s = new DeclarationStatement(d); |
1760 break; | 1777 break; |
1761 case T.LBrace: | 1778 case T.LBrace: |
1762 s = parseScopeStatement(); | 1779 s = parseScopeStatement(); |
1807 T.Not, | 1824 T.Not, |
1808 T.Tilde, | 1825 T.Tilde, |
1809 T.New, | 1826 T.New, |
1810 T.Delete, | 1827 T.Delete, |
1811 T.Cast: | 1828 T.Cast: |
1812 case_ExpressionStatement: | 1829 case_parseExpressionStatement: |
1813 s = new ExpressionStatement(parseExpression()); | 1830 s = new ExpressionStatement(parseExpression()); |
1814 require(T.Semicolon); | 1831 require(T.Semicolon); |
1815 break; | 1832 break; |
1816 default: | 1833 default: |
1817 if (token.isSpecialToken) | 1834 if (token.isSpecialToken) |
1818 goto case_ExpressionStatement; | 1835 goto case_parseExpressionStatement; |
1819 | 1836 |
1820 // Assert that this isn't a valid expression. | 1837 // Assert that this isn't a valid expression. |
1821 assert( | 1838 assert( |
1822 delegate bool(){ | 1839 delegate bool(){ |
1823 bool success; | 1840 bool success; |
3621 e = parseExpression(); | 3638 e = parseExpression(); |
3622 require(T.RParen); | 3639 require(T.RParen); |
3623 // TODO: create ParenExpression? | 3640 // TODO: create ParenExpression? |
3624 } | 3641 } |
3625 break; | 3642 break; |
3626 // BasicType . Identifier | 3643 // IntegralType . Identifier |
3627 case T.Char, T.Wchar, T.Dchar, T.Bool, | 3644 case T.Char, T.Wchar, T.Dchar, T.Bool, |
3628 T.Byte, T.Ubyte, T.Short, T.Ushort, | 3645 T.Byte, T.Ubyte, T.Short, T.Ushort, |
3629 T.Int, T.Uint, T.Long, T.Ulong, | 3646 T.Int, T.Uint, T.Long, T.Ulong, |
3630 T.Float, T.Double, T.Real, | 3647 T.Float, T.Double, T.Real, |
3631 T.Ifloat, T.Idouble, T.Ireal, | 3648 T.Ifloat, T.Idouble, T.Ireal, |
3902 } | 3919 } |
3903 set(t, begin); | 3920 set(t, begin); |
3904 return t; | 3921 return t; |
3905 } | 3922 } |
3906 | 3923 |
3907 Type parseCFunctionPointerType(Type type, ref Token* ident) | 3924 Type parseCFunctionPointerType(Type type, ref Token* ident, bool optionalParamList) |
3908 { | 3925 { |
3909 assert(token.type == T.LParen); | 3926 assert(token.type == T.LParen); |
3927 assert(type !is null); | |
3910 auto begin = token; | 3928 auto begin = token; |
3911 nT(); // Skip ( | 3929 nT(); // Skip ( |
3912 type = parseBasicType2(type); | 3930 type = parseBasicType2(type); |
3913 if (token.type == T.LParen) | 3931 if (token.type == T.LParen) |
3914 { | 3932 { |
3915 // Can be nested. | 3933 // Can be nested. |
3916 type = parseCFunctionPointerType(type, ident); | 3934 type = parseCFunctionPointerType(type, ident, true); |
3917 } | 3935 } |
3918 else if (token.type == T.Identifier) | 3936 else if (token.type == T.Identifier) |
3919 { | 3937 { |
3920 // The identifier of the function pointer and the declaration. | 3938 // The identifier of the function pointer and the declaration. |
3921 ident = token; | 3939 ident = token; |
3922 nT(); | 3940 nT(); |
3923 type = parseDeclaratorSuffix(type); | 3941 type = parseDeclaratorSuffix(type); |
3924 } | 3942 } |
3925 require(T.RParen); | 3943 require(T.RParen); |
3926 // Optional parameter list | 3944 |
3927 auto params = token.type == T.LParen ? parseParameterList() : null; | 3945 Parameters params; |
3946 if (optionalParamList) | |
3947 params = token.type == T.LParen ? parseParameterList() : null; | |
3948 else | |
3949 params = parseParameterList(); | |
3950 | |
3928 type = set(new CFuncPointerType(type, params), begin); | 3951 type = set(new CFuncPointerType(type, params), begin); |
3929 return type; | 3952 return type; |
3930 } | 3953 } |
3931 | 3954 |
3932 Type parseDeclarator(ref Token* ident, bool identOptional = false) | 3955 Type parseDeclarator(ref Token* ident, bool identOptional = false) |
3933 { | 3956 { |
3934 auto t = parseType(); | 3957 auto t = parseType(); |
3935 | 3958 |
3936 if (token.type == T.LParen) | 3959 if (token.type == T.LParen) |
3937 { | 3960 { |
3938 t = parseCFunctionPointerType(t, ident); | 3961 t = parseCFunctionPointerType(t, ident, true); |
3939 } | 3962 } |
3940 else if (token.type == T.Identifier) | 3963 else if (token.type == T.Identifier) |
3941 { | 3964 { |
3942 ident = token; | 3965 ident = token; |
3943 nT(); | 3966 nT(); |