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 }