Mercurial > projects > dil
comparison trunk/src/dil/Parser.d @ 496:5a607597dc22
Improved error recovery in the Parser.
The Parser skips to the next valid token if an illegal Declaration, Statement
or AsmInstruction was found.
Refactored a few things in Lexer.d and LexerFuncs.d.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Sun, 09 Dec 2007 13:04:15 +0100 |
parents | b60450804b6e |
children | 949a53332c66 |
comparison
equal
deleted
inserted
replaced
495:b60450804b6e | 496:5a607597dc22 |
---|---|
343 decl = new EmptyDeclaration(); | 343 decl = new EmptyDeclaration(); |
344 break; | 344 break; |
345 // Declaration | 345 // Declaration |
346 case T.Identifier, T.Dot, T.Typeof: | 346 case T.Identifier, T.Dot, T.Typeof: |
347 // IntegralType | 347 // IntegralType |
348 case T.Char, T.Wchar, T.Dchar, T.Bool, | 348 case T.Char, T.Wchar, T.Dchar, T.Bool, |
349 T.Byte, T.Ubyte, T.Short, T.Ushort, | 349 T.Byte, T.Ubyte, T.Short, T.Ushort, |
350 T.Int, T.Uint, T.Long, T.Ulong, | 350 T.Int, T.Uint, T.Long, T.Ulong, |
351 T.Float, T.Double, T.Real, | 351 T.Float, T.Double, T.Real, |
352 T.Ifloat, T.Idouble, T.Ireal, | 352 T.Ifloat, T.Idouble, T.Ireal, |
353 T.Cfloat, T.Cdouble, T.Creal, T.Void: | 353 T.Cfloat, T.Cdouble, T.Creal, T.Void: |
354 case_Declaration: | 354 case_Declaration: |
355 return parseVariableOrFunction(this.storageClass, this.protection, this.linkageType); | 355 return parseVariableOrFunction(this.storageClass, this.protection, this.linkageType); |
356 /+case T.Module: | 356 /+case T.Module: |
357 // TODO: Error: module is optional and can appear only once at the top of the source file. | 357 // TODO: Error: module is optional and can appear only once at the top of the source file. |
358 break;+/ | 358 break;+/ |
359 default: | 359 default: |
360 error(MID.ExpectedButFound, "Declaration", token.srcText); | 360 decl = new IllegalDeclaration(); |
361 decl = new IllegalDeclaration(token); | 361 // Skip to next valid token. |
362 nT(); | 362 do |
363 nT(); | |
364 while (!token.isDeclDefStart && | |
365 token.type != T.RBrace && | |
366 token.type != T.EOF) | |
367 auto text = Token.textSpan(begin, this.prevToken); | |
368 error(begin, "illegal Declaration found: " ~ text); | |
363 } | 369 } |
364 decl.setProtection(this.protection); | 370 decl.setProtection(this.protection); |
365 decl.setStorageClass(this.storageClass); | 371 decl.setStorageClass(this.storageClass); |
366 assert(!isNodeSet(decl)); | 372 assert(!isNodeSet(decl)); |
367 set(decl, begin); | 373 set(decl, begin); |
700 case "System": | 706 case "System": |
701 linkageType = LinkageType.System; | 707 linkageType = LinkageType.System; |
702 break; | 708 break; |
703 default: | 709 default: |
704 error(MID.UnrecognizedLinkageType, token.srcText); | 710 error(MID.UnrecognizedLinkageType, token.srcText); |
705 nT(); | |
706 } | 711 } |
707 require(T.RParen); | 712 require(T.RParen); |
708 return linkageType; | 713 return linkageType; |
709 } | 714 } |
710 | 715 |
711 void checkLinkageType(ref LinkageType prev_lt, LinkageType lt, char* tokStart) | 716 void checkLinkageType(ref LinkageType prev_lt, LinkageType lt, Token* begin) |
712 { | 717 { |
713 if (prev_lt == LinkageType.None) | 718 if (prev_lt == LinkageType.None) |
714 prev_lt = lt; | 719 prev_lt = lt; |
715 else | 720 else |
716 // TODO: create new msg RedundantLinkageType. | 721 // TODO: create new msg RedundantLinkageType. |
717 error(MID.RedundantStorageClass, tokStart[0 .. prevToken.end - tokStart]); | 722 error(begin, "redundant linkage type: " ~ Token.textSpan(begin, this.prevToken)); |
718 } | 723 } |
719 | 724 |
720 Declaration parseStorageAttribute() | 725 Declaration parseStorageAttribute() |
721 { | 726 { |
722 StorageClass stc, stc_tmp; | 727 StorageClass stc, stc_tmp; |
737 goto Lcommon; | 742 goto Lcommon; |
738 } | 743 } |
739 | 744 |
740 nT(); | 745 nT(); |
741 auto linkageType = parseLinkageType(); | 746 auto linkageType = parseLinkageType(); |
742 checkLinkageType(prev_linkageType, linkageType, begin.start); | 747 checkLinkageType(prev_linkageType, linkageType, begin); |
743 | 748 |
744 auto saved = this.linkageType; // Save. | 749 auto saved = this.linkageType; // Save. |
745 this.linkageType = linkageType; // Set. | 750 this.linkageType = linkageType; // Set. |
746 decl = new LinkageDeclaration(linkageType, parse()); | 751 decl = new LinkageDeclaration(linkageType, parse()); |
747 set(decl, begin); | 752 set(decl, begin); |
1741 if (success) | 1746 if (success) |
1742 goto LreturnDeclarationStatement; // Declaration | 1747 goto LreturnDeclarationStatement; // Declaration |
1743 else | 1748 else |
1744 goto case_parseExpressionStatement; // Expression | 1749 goto case_parseExpressionStatement; // Expression |
1745 // IntegralType | 1750 // IntegralType |
1746 case T.Char, T.Wchar, T.Dchar, T.Bool, | 1751 case T.Char, T.Wchar, T.Dchar, T.Bool, |
1747 T.Byte, T.Ubyte, T.Short, T.Ushort, | 1752 T.Byte, T.Ubyte, T.Short, T.Ushort, |
1748 T.Int, T.Uint, T.Long, T.Ulong, | 1753 T.Int, T.Uint, T.Long, T.Ulong, |
1749 T.Float, T.Double, T.Real, | 1754 T.Float, T.Double, T.Real, |
1750 T.Ifloat, T.Idouble, T.Ireal, | 1755 T.Ifloat, T.Idouble, T.Ireal, |
1751 T.Cfloat, T.Cdouble, T.Creal, T.Void: | 1756 T.Cfloat, T.Cdouble, T.Creal, T.Void: |
1752 case_parseDeclaration: | 1757 case_parseDeclaration: |
1753 d = parseVariableOrFunction(); | 1758 d = parseVariableOrFunction(); |
1887 // case T.Mixin: | 1892 // case T.Mixin: |
1888 case T.Import: | 1893 case T.Import: |
1889 case T.Typeid: | 1894 case T.Typeid: |
1890 case T.Is: | 1895 case T.Is: |
1891 case T.LParen: | 1896 case T.LParen: |
1892 // IntegralType | 1897 /+ // IntegralType |
1893 /+case T.Char, T.Wchar, T.Dchar, T.Bool, | 1898 case T.Char, T.Wchar, T.Dchar, T.Bool, |
1894 T.Byte, T.Ubyte, T.Short, T.Ushort, | 1899 T.Byte, T.Ubyte, T.Short, T.Ushort, |
1895 T.Int, T.Uint, T.Long, T.Ulong, | 1900 T.Int, T.Uint, T.Long, T.Ulong, |
1896 T.Float, T.Double, T.Real, | 1901 T.Float, T.Double, T.Real, |
1897 T.Ifloat, T.Idouble, T.Ireal, | 1902 T.Ifloat, T.Idouble, T.Ireal, |
1898 T.Cfloat, T.Cdouble, T.Creal, T.Void:+/ | 1903 T.Cfloat, T.Cdouble, T.Creal, T.Void:+/ |
1899 case T.Traits: // D2.0 | 1904 case T.Traits: // D2.0 |
1900 // Tokens that can start a UnaryExpression: | 1905 // Tokens that can start a UnaryExpression: |
1917 if (token.isSpecialToken) | 1922 if (token.isSpecialToken) |
1918 goto case_parseExpressionStatement; | 1923 goto case_parseExpressionStatement; |
1919 | 1924 |
1920 if (token.type != T.Dollar) | 1925 if (token.type != T.Dollar) |
1921 // Assert that this isn't a valid expression. | 1926 // Assert that this isn't a valid expression. |
1922 assert( | 1927 assert(delegate bool(){ |
1923 delegate bool(){ | |
1924 bool success; | 1928 bool success; |
1925 auto expression = try_(&parseExpression, success); | 1929 auto expression = try_(&parseExpression, success); |
1926 return success; | 1930 return success; |
1927 }() == false, "Didn't expect valid expression." | 1931 }() == false, "Didn't expect valid expression." |
1928 ); | 1932 ); |
1929 | 1933 |
1930 // Report error: it's an illegal statement. | 1934 // Report error: it's an illegal statement. |
1931 error(MID.ExpectedButFound, "Statement", token.srcText); | 1935 s = new IllegalStatement(); |
1932 s = new IllegalStatement(token); | 1936 // Skip to next valid token. |
1933 nT(); | 1937 do |
1938 nT(); | |
1939 while (!token.isStatementStart && | |
1940 token.type != T.RBrace && | |
1941 token.type != T.EOF) | |
1942 auto text = Token.textSpan(begin, this.prevToken); | |
1943 error(begin, "illegal Statement found: " ~ text); | |
1934 } | 1944 } |
1935 assert(s !is null); | 1945 assert(s !is null); |
1936 set(s, begin); | 1946 set(s, begin); |
1937 return s; | 1947 return s; |
1938 } | 1948 } |
2014 goto Lcommon; | 2024 goto Lcommon; |
2015 } | 2025 } |
2016 | 2026 |
2017 nT(); | 2027 nT(); |
2018 auto linkageType = parseLinkageType(); | 2028 auto linkageType = parseLinkageType(); |
2019 checkLinkageType(prev_linkageType, linkageType, begin.start); | 2029 checkLinkageType(prev_linkageType, linkageType, begin); |
2020 | 2030 |
2021 d = new LinkageDeclaration(linkageType, parse()); | 2031 d = new LinkageDeclaration(linkageType, parse()); |
2022 break; | 2032 break; |
2023 case T.Static: | 2033 case T.Static: |
2024 stc_tmp = StorageClass.Static; | 2034 stc_tmp = StorageClass.Static; |
2719 case T.Semicolon: | 2729 case T.Semicolon: |
2720 s = new EmptyStatement(); | 2730 s = new EmptyStatement(); |
2721 nT(); | 2731 nT(); |
2722 break; | 2732 break; |
2723 default: | 2733 default: |
2724 error(MID.ExpectedButFound, "AsmInstruction", token.srcText); | 2734 s = new IllegalAsmInstruction(); |
2725 s = new IllegalAsmInstruction(token); | 2735 // Skip to next valid token. |
2726 nT(); | 2736 do |
2737 nT(); | |
2738 while (!token.isAsmInstructionStart && | |
2739 token.type != T.RBrace && | |
2740 token.type != T.EOF) | |
2741 auto text = Token.textSpan(begin, this.prevToken); | |
2742 error(begin, "illegal AsmInstruction found: " ~ text); | |
2727 } | 2743 } |
2728 set(s, begin); | 2744 set(s, begin); |
2729 return s; | 2745 return s; |
2730 } | 2746 } |
2731 | 2747 |
3734 require(T.RParen); | 3750 require(T.RParen); |
3735 // TODO: create ParenExpression? | 3751 // TODO: create ParenExpression? |
3736 } | 3752 } |
3737 break; | 3753 break; |
3738 // IntegralType . Identifier | 3754 // IntegralType . Identifier |
3739 case T.Char, T.Wchar, T.Dchar, T.Bool, | 3755 case T.Char, T.Wchar, T.Dchar, T.Bool, |
3740 T.Byte, T.Ubyte, T.Short, T.Ushort, | 3756 T.Byte, T.Ubyte, T.Short, T.Ushort, |
3741 T.Int, T.Uint, T.Long, T.Ulong, | 3757 T.Int, T.Uint, T.Long, T.Ulong, |
3742 T.Float, T.Double, T.Real, | 3758 T.Float, T.Double, T.Real, |
3743 T.Ifloat, T.Idouble, T.Ireal, | 3759 T.Ifloat, T.Idouble, T.Ireal, |
3744 T.Cfloat, T.Cdouble, T.Creal, T.Void: | 3760 T.Cfloat, T.Cdouble, T.Creal, T.Void: |
3745 auto type = new IntegralType(token.type); | 3761 auto type = new IntegralType(token.type); |
3746 nT(); | 3762 nT(); |
3834 Type t; | 3850 Type t; |
3835 // IdentifierType tident; | 3851 // IdentifierType tident; |
3836 | 3852 |
3837 switch (token.type) | 3853 switch (token.type) |
3838 { | 3854 { |
3839 case T.Char, T.Wchar, T.Dchar, T.Bool, | 3855 case T.Char, T.Wchar, T.Dchar, T.Bool, |
3840 T.Byte, T.Ubyte, T.Short, T.Ushort, | 3856 T.Byte, T.Ubyte, T.Short, T.Ushort, |
3841 T.Int, T.Uint, T.Long, T.Ulong, | 3857 T.Int, T.Uint, T.Long, T.Ulong, |
3842 T.Float, T.Double, T.Real, | 3858 T.Float, T.Double, T.Real, |
3843 T.Ifloat, T.Idouble, T.Ireal, | 3859 T.Ifloat, T.Idouble, T.Ireal, |
3844 T.Cfloat, T.Cdouble, T.Creal, T.Void: | 3860 T.Cfloat, T.Cdouble, T.Creal, T.Void: |
3845 t = new IntegralType(token.type); | 3861 t = new IntegralType(token.type); |
3846 nT(); | 3862 nT(); |
4449 else | 4465 else |
4450 error(MID.ExpectedButFound, "Identifier", token.srcText); | 4466 error(MID.ExpectedButFound, "Identifier", token.srcText); |
4451 return null; | 4467 return null; |
4452 } | 4468 } |
4453 | 4469 |
4470 /// Reports an error that has no message ID yet. | |
4471 void error(Token* token, char[] formatMsg, ...) | |
4472 { | |
4473 error_(token, MID.min, formatMsg, _arguments, _argptr); | |
4474 } | |
4475 | |
4454 void error(MID mid, ...) | 4476 void error(MID mid, ...) |
4477 { | |
4478 error_(this.token, mid, GetMsg(mid), _arguments, _argptr); | |
4479 } | |
4480 | |
4481 void error_(Token* token, MID mid, char[] formatMsg, TypeInfo[] _arguments, void* _argptr) | |
4455 { | 4482 { |
4456 if (trying) | 4483 if (trying) |
4457 { | 4484 { |
4458 ++errorCount; | 4485 ++errorCount; |
4459 return; | 4486 return; |
4460 } | 4487 } |
4461 auto location = this.token.getLocation(); | 4488 auto location = token.getLocation(); |
4462 auto msg = Format(_arguments, _argptr, GetMsg(mid)); | 4489 auto msg = Format(_arguments, _argptr, formatMsg); |
4463 errors ~= new Information(InfoType.Parser, mid, location, msg); | 4490 errors ~= new Information(InfoType.Parser, mid, location, msg); |
4464 } | 4491 } |
4465 } | 4492 } |