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();