text: #pragma once
  #include "Parser.hpp"
  
  struct C : public Grammar
  {
  	enum Type
  	{
  		EnumConstant, 
  
  		Letter, Digit, NonZeroDigit, BinaryDigit, OctalDigit, HexadecimalDigit, Alnum, NotAlnum,
  
  		Spaces,
  
  		IdentifierStartCharacter, IdentifierCharacter, Identifier,
  
  		// Constants
  		Constant,
  		IntegerConstant,
  		DecimalConstant, BinaryConstant, OctalConstant, HexadecimalConstant,
  		BinaryPrefix, IntegerSuffix, UnsignedSuffix, LongSuffix, LongLongSuffix, HexadecimalPrefix,
  
  		FloatingConstant,
  		DecimalFloatingConstant, HexadecimalFloatingConstant,
  		FractionalConstant, ExponentPart, Sign, DigitSequence, HexadecimalFractionalConstant,
  		BinaryExponentPart, HexadecimalDigitSequence, FloatingSuffix,
  
  		CharacterConstant,
  		CCharSequence, CChar,
  
  		// String literal
  		StringLiteral,
  		SCharSequence, SChar,
  
  		// Expressions
  		PrimaryExpression, PostfixExpression, PostfixExpressionRecursion, ArgumentExpressionList, UnaryExpression,
  		UnaryOperator, CastExpression, MultiplicativeExpression, AdditiveExpression, ShiftExpression,
  		RelationalExpression, EqualityExpression, AndExpression, XOrExpression, IOrExpression,
  		LAndExpression, LOrExpression, ConditionalExpression, AssignmentExpression, AssignmentOperator,
  		Expression, ConstantExpression,
  
  
  		Statement, LabeledStatement, CompoundStatement, ExpressionStatement, SelectionStatement, IterationStatement, JumpStatement,
  
  		Declaration, DeclarationSpecifiers, AttributeSeq, Attribute, InitDeclaratorList, InitDeclarator, StorageClassSpecifier, 
  		ExtendedDeclModifierSeq, ExtendedDeclModifier, TypeSpecifier, StructOrUnionSpecifier, StructOrUnion, StructDeclarationList,
  		StructDeclaration, SpecifierQualifierList, StructDeclaratorList, StructDeclarator, EnumSpecifier, EnumeratorList, Enumerator,
  		AtomicTypeSpecifier, TypeQualifier, FunctionSpecifier, AlignmentSpecifier, Declarator, DirectDeclarator, Pointer, TypeQualifierList,
  		ParameterTypeList, ParameterList, ParameterDeclaration, IdenfierList, TypeName, AbstractDeclarator, DirectAbstractDeclarator,
  		TypedefName, Initializer, InitializerList, Designation, DesignatorList, Designator, StaticAssertDeclaration, FunctionDeclarationSpecifiers,
  
  		TranslationUnit, ExternalDeclaration, FunctionDefinition,
  
  		LotsOfConstants, LotsOfExpressions, LotsOfStatements, LotsOfDeclarations
  	};
  
  	Parser& Char(char v) { return satisfy(func((char a), a == v)); }
  	Parser& String(view val) { return val.empty() ? unit("") : (Char(val[0]) > String(val.substr(1)) > unit(val) | unit()); }
  	Parser& Whitespace(Parser& p) { return Spaces > p < Spaces; }
  	Parser& Symbol(view val) { return Whitespace(String(val)); }
  
  	void Init() override
  	{
  		parseQ(Sign) = Char('-') | Char('+');
  		parseQ(Letter) = satisfy(std::isalpha);
  		parseQ(Digit) = satisfy(std::isdigit);
  		parseQ(Alnum) = satisfy(std::isalnum);
  		parseQ(NotAlnum) = satisfy(func((char c), !std::isalnum(c)));
  		parseQ(NonZeroDigit) = satisfy(func((char c), c != '0' && std::isdigit(c)));
  		parseQ(BinaryDigit) = satisfy(func((char c), c == '0' || c == '1'));
  		parseQ(OctalDigit) = satisfy(func((char c), c != '9' && c != '8' && std::isdigit(c)));
  		parseQ(HexadecimalDigit) = satisfy(std::isxdigit);
  
  		parseQ(DigitSequence) = some(*Digit);
  		parseQ(HexadecimalDigitSequence) = some(*HexadecimalDigit);
  		parseQ(Spaces) = many(satisfy(std::isspace));
  
  		parseQ(IdentifierStartCharacter) = Letter | Char('_');
  		parseQ(IdentifierCharacter) = IdentifierStartCharacter | Digit;
  		parse(Identifier) = Identifier & Whitespace(IdentifierStartCharacter * many(*IdentifierCharacter));
  
  		parse(Constant) =
  			  FloatingConstant  & FloatingConstant
  			| IntegerConstant   & IntegerConstant
  			| EnumConstant      & EnumConstant
  			| CharacterConstant & CharacterConstant;
  
  		parse(EnumConstant) = Identifier;
  
  
  		// Integer Constants
  		parse(IntegerConstant) =
  			  DecimalConstant     & DecimalConstant * optional(*IntegerSuffix)
  			| HexadecimalConstant & HexadecimalConstant * optional(*IntegerSuffix)
  			| BinaryConstant      & BinaryConstant * optional(*IntegerSuffix)
  			| OctalConstant       & OctalConstant * optional(*IntegerSuffix);
  
  		parse(DecimalConstant) = NonZeroDigit * many(*Digit);
  
  		parse(BinaryConstant) = BinaryPrefix * some(*BinaryDigit);
  		parse(BinaryPrefix) = String("0b") | String("0B");
  
  		parse(OctalConstant) = Char('0') * some(*OctalDigit);
  
  		parse(HexadecimalConstant) = HexadecimalPrefix * HexadecimalDigitSequence;
  		parse(HexadecimalPrefix) = String("0x") | String("0X");
  
  		parse(IntegerSuffix) =
     			  UnsignedSuffix * optional(LongLongSuffix | LongSuffix)
  			| (LongLongSuffix | LongSuffix) * optional(*UnsignedSuffix);
  
  		parse(UnsignedSuffix) = Char('u') | Char('U');
  		parse(LongSuffix) = Char('l') | Char('L');
  		parse(LongLongSuffix) = String("ll") | String("LL");
  
  
  		// Floating Constants
  		parse(FloatingConstant) =
  			  DecimalFloatingConstant & DecimalFloatingConstant * optional(*FloatingSuffix)
  			| HexadecimalFloatingConstant & HexadecimalFloatingConstant * optional(*FloatingSuffix);
  
  		parse(DecimalFloatingConstant) =
  			  FractionalConstant * optional(*ExponentPart)
  			| DigitSequence * ExponentPart;
  
  		parse(FractionalConstant) =
  			  optional(*DigitSequence) * Char('.') * DigitSequence
  			| DigitSequence * Char('.');
  
  		parse(ExponentPart) = (Char('e') | Char('E')) * optional(*Sign) * DigitSequence;
  
  		parse(HexadecimalFloatingConstant) =
  			HexadecimalPrefix * (
  				  HexadecimalFractionalConstant * BinaryExponentPart
  			    | HexadecimalDigitSequence * BinaryExponentPart
  		    );
  
  		parse(HexadecimalFractionalConstant) =
  			  optional(*HexadecimalDigitSequence) * Char('.') * HexadecimalDigitSequence
  			| HexadecimalDigitSequence * Char('.');
  
  		parse(BinaryExponentPart) =
  			(Char('p') | Char('P')) * optional(*Sign) * DigitSequence;
  
  		parse(FloatingSuffix) = Char('f') | Char('l') | Char('F') | Char('L');
  
  
  		// Character constant
  		parse(CharacterConstant) = Char('\'') > CCharSequence < Char('\'');
  		parseQ(CCharSequence) = some(*CChar);
  		parseQ(CChar) = satisfy(func((char c), c != '\'' && c != '\\' && c != '\n'));
  
  
  		// String Literal
  		parse(StringLiteral) = Whitespace(Char('"') > optional(*SCharSequence) < Char('"'));
  		parseQ(SCharSequence) = some(*SChar);
  		parseQ(SChar) = satisfy(func((char c), c != '"' && c != '\\' && c != '\n'));
  
  
  		// Expression
  		parse(PrimaryExpression) =
  			  Identifier
  			| Constant
  			| StringLiteral & StringLiteral
  			| Char('(') * Expression * Char(')');
  
  		parse(PostfixExpression) = PrimaryExpression * many(*PostfixExpressionRecursion);
  
  		parse(PostfixExpressionRecursion) =
  			  Symbol("[")  * Expression * Symbol("]")
  			| Symbol("(")  * ArgumentExpressionList * Symbol(")")
  			| Symbol(".")  * Identifier
  			| Symbol("->") * Identifier
  			| Symbol("++")
  			| Symbol("--")
  			| Symbol("(") * TypeName * Symbol(")") * Symbol("{") * InitializerList * optional(Symbol(",")) * Symbol("}");
  
  		parse(UnaryExpression) =
  			  Symbol("++")     * UnaryExpression
  			| Symbol("--")     * UnaryExpression
  			| Symbol("sizeof") * (Symbol("(") * TypeName * Symbol(")") | UnaryExpression)
  			| UnaryOperator    * CastExpression
  			| PostfixExpression;
  
  		parse(AssignmentOperator)       = Whitespace(String("=") | String("*=")  | String("/=")  | String("%=") | String("+=") | String("-=") 
  			                                                     | String("<<=") | String(">>=") | String("&=") | String("^=") | String("|="));
  		
  		parse(UnaryOperator)            = Whitespace(satisfy(func((char c), c == '&' || c == '*' || c == '+' || c == '-' || c == '~' || c == '!')));
  
  		parse(ConstantExpression)       = ConditionalExpression;
  		parse(CastExpression)           = UnaryExpression | some(Symbol("(") * TypeName * Symbol(")")) * UnaryExpression;
  		parse(MultiplicativeExpression) = CastExpression           * many(Whitespace((String("*")  | String("/")  | String("%")                )) * MultiplicativeExpression);
  		parse(AdditiveExpression)       = MultiplicativeExpression * many(Whitespace((String("+")  | String("-")                               )) * AdditiveExpression);
  		parse(ShiftExpression)          = AdditiveExpression       * many(Whitespace((String(">>") | Symbol("<<")                              )) * ShiftExpression);
  		parse(RelationalExpression)     = ShiftExpression          * many(Whitespace((String("<")  | String(">")  | String("<=") | String(">="))) * RelationalExpression);
  		parse(EqualityExpression)       = RelationalExpression     * many(Whitespace((String("==") | String("!=")                              )) * EqualityExpression);
  		parse(AndExpression)            = EqualityExpression       * many(Symbol("&")  * AndExpression);
  		parse(XOrExpression)            = AndExpression            * many(Symbol("^")  * XOrExpression);
  		parse(IOrExpression)            = XOrExpression            * many(Symbol("|")  * IOrExpression);
  		parse(LAndExpression)           = IOrExpression            * many(Symbol("&&") * LAndExpression);
  		parse(LOrExpression)            = LAndExpression           * many(Symbol("||") * LOrExpression);
  		parse(ConditionalExpression)    = LOrExpression            * many(Symbol("?")  * Expression * Symbol(":") * ConditionalExpression);
  		parse(ArgumentExpressionList)   = AssignmentExpression     * many(Symbol(",")  * AssignmentExpression);
  		parse(Expression)               = AssignmentExpression     * many(Symbol(",")  * Expression);
  
  		parse(AssignmentExpression)     = UnaryExpression * AssignmentOperator * AssignmentExpression | ConditionalExpression;
  
  		// Statements
  		parse(Statement) = JumpStatement | IterationStatement | SelectionStatement | ExpressionStatement | CompoundStatement | LabeledStatement;
  
  		parse(JumpStatement) =
  			  Symbol("goto") * Identifier * Char(';')
  			| Symbol("continue") * Char(';')
  			| Symbol("break") * Char(';')
  			| Symbol("return") * optional(*Expression) * Char(';');
  
  		parse(CompoundStatement) = Symbol("{") * many(*Declaration) * many(*Statement) * Symbol("}");
  
  		parse(ExpressionStatement) = optional(*Expression) * Symbol(";");
  
  		parse(IterationStatement) =
  			  Symbol("while") * Symbol("(") * Expression * Symbol(")") * Statement
  			| Symbol("do") * Statement * Symbol("while") * Symbol("(") * Expression * Symbol(")") * Symbol(";")
  			| Symbol("for") * Symbol("(") * optional(*Expression) * Symbol(";") * optional(*Expression) * Symbol(";") * optional(*Expression) * Symbol(")") * Statement;
  
  		parse(SelectionStatement) = 
  			  Symbol("if") * Symbol("(") * Expression * Symbol(")") * Statement
  			| Symbol("if") * Symbol("(") * Expression * Symbol(")") * Statement * Symbol("else") * Statement
  			| Symbol("switch") * Symbol("(") * Expression * Symbol(")") * Statement;
  
  		parse(LabeledStatement) =
  			  Identifier * Symbol(":") * Statement
  			| Symbol("case") * ConstantExpression * Symbol(":") * Statement
  			| Symbol("default") * Symbol(":") * Statement;
  
  		// Declarations
  		parse(Declaration) = 
  			  DeclarationSpecifiers * optional(*AttributeSeq) * optional(*InitDeclaratorList) * Symbol(";")
  			| StaticAssertDeclaration;
  
  		parse(DeclarationSpecifiers) =
  			(some(AlignmentSpecifier | StorageClassSpecifier | TypeQualifier | FunctionSpecifier) | TypeSpecifier)
  			| (TypeSpecifier | some(AlignmentSpecifier | StorageClassSpecifier | TypeQualifier | FunctionSpecifier));
  
  		parse(FunctionDeclarationSpecifiers) =
  			(some(AlignmentSpecifier | StorageClassSpecifier | TypeQualifier | FunctionSpecifier) | TypeSpecifier)
  			|  (TypeSpecifier | some(AlignmentSpecifier | StorageClassSpecifier | TypeQualifier | FunctionSpecifier));
  
  		parse(AttributeSeq) =
  			some(*Attribute);
  
  		parse(Attribute) =
  			Symbol("__asm") | Symbol("__based")  | Symbol("__cdecl")   | Symbol("__clrcall")  | Symbol("__fastcall") 
  			                | Symbol("__inline") | Symbol("__stdcall") | Symbol("__thiscall") | Symbol("__vectorcall");
  			
  		parse(InitDeclaratorList) = InitDeclarator * many(Symbol(",") * InitDeclarator);
  
  		parse(InitDeclarator) = Declarator * optional(Symbol("=") * Initializer);
  
  		parse(StorageClassSpecifier) =
  			Symbol("auto") | Symbol("extern")  | Symbol("register") | Symbol("static") | Symbol("_Thread_local")
  			| Symbol("typedef") | (Symbol("__declspec") * Symbol("(") * ExtendedDeclModifierSeq * Symbol(")"));
  
  		parse(ExtendedDeclModifierSeq) = many(*ExtendedDeclModifier);
  		parse(ExtendedDeclModifier) = Symbol("thread") | Symbol("naked") | Symbol("dllimport") | Symbol("dllexport");
  
  		parse(TypeSpecifier) =
  			AtomicTypeSpecifier | StructOrUnionSpecifier | EnumSpecifier    | Symbol("void")     | Symbol("char")    | 
  			Symbol("short")     | Symbol("int")          | Symbol("__int8") | Symbol("__int16")  | Symbol("__int32") | 
  			Symbol("__int64")   | Symbol("long")         | Symbol("float")  | Symbol("double")   |
  			Symbol("signed")    | Symbol("unsigned")     | Symbol("_Bool")  | Symbol("_Complex") | TypedefName;
  
  		parse(StructOrUnionSpecifier) =
  			StructOrUnion * (
  				  optional(*Identifier) * Symbol("{") * StructDeclarationList * Symbol("}") 
  				| Identifier);
  
  		parse(StructOrUnion) = Symbol("struct") | Symbol("union");
  
  		parse(StructDeclarationList) = some(*StructDeclaration);
  		parse(StructDeclaration) = SpecifierQualifierList * optional(*StructDeclaratorList) * Symbol(";") | StaticAssertDeclaration;
  
  		parse(SpecifierQualifierList) = some(AlignmentSpecifier | TypeQualifier | TypeSpecifier);
  
  		parse(StructDeclaratorList) = StructDeclarator * many(Symbol(",") * StructDeclarator);
  
  		parse(StructDeclarator) = optional(*Declarator) * Symbol(":") * ConstantExpression | Declarator;
  
  		parse(EnumSpecifier) = 
  			Symbol("enum") * (
  				  optional(*Identifier) * Symbol("{") * EnumeratorList * optional(Symbol(",")) * Symbol("}")
  				| Identifier);
  
  		parse(EnumeratorList) = Enumerator * many(Symbol(",") * Enumerator);
  		parse(Enumerator) = EnumConstant * optional(Symbol("=") * ConstantExpression);
  
  		parse(AtomicTypeSpecifier) = Symbol("_Atomic") * Symbol("(") * TypeName * Symbol(")");
  
  		parse(TypeQualifier) = Symbol("const") | Symbol("restrict") | Symbol("volatile") | Symbol("_Atomic");
  
  		parse(FunctionSpecifier) = Symbol("inline") | Symbol("_Noreturn");
  
  		parse(AlignmentSpecifier) = Symbol("_Alignas") * Symbol("(") * (TypeName | ConstantExpression) * Symbol(")");
  		
  		parse(Declarator) = optional(*Pointer) * DirectDeclarator;
  
  		parse(DirectDeclarator) =
  			  (Identifier | Symbol("(") * Declarator * Symbol(")")) * many(
  				Symbol("[") * (
  					  Symbol("static") * optional(*TypeQualifierList) * AssignmentExpression
  					| TypeQualifierList * Symbol("static") * AssignmentExpression
  					| optional(*TypeQualifierList) * (Symbol("*") | optional(*AssignmentExpression))
  					) * Symbol("]")
  				| Symbol("(") * (
  					  ParameterTypeList
  					| optional(Identifier * many(Symbol(",") * Identifier))
  					) * Symbol(")"));
  
  		parse(Pointer) = some(Symbol("*") * optional(*TypeQualifierList));
  
  		parse(TypeQualifierList) = some(*TypeQualifier);
  
  		parse(ParameterTypeList) = ParameterList * optional(Symbol(",") * Symbol("..."));
  		parse(ParameterList) = ParameterDeclaration * many(Symbol(",") * ParameterDeclaration);
  
  		parse(ParameterDeclaration) = DeclarationSpecifiers * (Declarator | optional(*AbstractDeclarator));
  
  		parse(TypeName) = SpecifierQualifierList * optional(*AbstractDeclarator);
  
  		parse(AbstractDeclarator) = optional(*Pointer) * DirectAbstractDeclarator | Pointer;
  
  		parse(DirectAbstractDeclarator) = 
  			  (Symbol("(") * (AbstractDeclarator | optional(*ParameterTypeList)) * Symbol(")")) * many(
  				Symbol("[") * (
  					  Symbol("static") * optional(*TypeQualifierList) * AssignmentExpression
  					| TypeQualifierList * Symbol("static") * AssignmentExpression
  					| optional(*TypeQualifierList) * (Symbol("*") | optional(*AssignmentExpression))
  					) * Symbol("]")
  				| Symbol("(") * optional(*ParameterTypeList) * Symbol(")"));
  
  		parse(TypedefName) = Identifier;
  
  		parse(Initializer) = 
  			  Symbol("{") * InitializerList * optional(Symbol(",")) * Symbol("}")
  			| AssignmentExpression;
  
  		parse(InitializerList) =
  			optional(*Designator) * Initializer * many(Symbol(",") * optional(*Designator) * Initializer);
  
  		parse(Designation) = DesignatorList * Symbol("=");
  
  		parse(DesignatorList) = some(*Designator);
  
  		parse(Designator) = Symbol("[") * ConstantExpression * Symbol("]") | Symbol(".") * Identifier;
  
  		parse(StaticAssertDeclaration) = Symbol("_Static_assert") * Symbol("(") * ConstantExpression * Symbol(",") * StringLiteral * Symbol(")") * Symbol(";");
  
  		parse(TranslationUnit) = some(*ExternalDeclaration);
  
  		parse(ExternalDeclaration) = FunctionDefinition | Declaration;
  
  		parse(FunctionDefinition) = optional(*FunctionDeclarationSpecifiers) * Declarator * optional(some(*Declaration)) * CompoundStatement;
  
  
  		parse(LotsOfConstants) =
  			many(Whitespace(*Constant));
  
  		parse(LotsOfExpressions) =
  			many(Whitespace(*Expression));
  
  		parse(LotsOfStatements) =
  			many(Whitespace(*Statement));
  
  		parse(LotsOfDeclarations) =
  			many(Whitespace(*Declaration));
  	}
  
  	// Tests :
  	std::string constants = code(
  
  		123     123u     123l     123ul     123lu     123ll     123ull     123llu        // Decimal
  		0123    0123u    0123l    0123ul    0123lu    0123ll    0123ull    0123llu       // Octal
  		0x123   0x123u   0x123l   0x123ul   0x123lu   0x123ll   0x123ull   0x123llu      // Hex
  		0b10101 0b10101u 0b10101l 0b10101ul 0b10101lu 0b10101ll 0b10101ull 0b10101llu    // Binary
  
  		123.    123.f    123.l    0.123    0.123f    0.123l    .123    .123f    .123l    // Float
  		123.e4  123.e4f  123.e4l  0.123e4  0.123e4f  0.123e4l  .123e4  .123e4f  .123e4l  // Power
  		123.e-4 123.e-4f 123.e-4l 0.123e-4 0.123e-4f 0.123e-4l .123e-4 .123e-4f .123e-4l // - Sign Power
  		123.e+4 123.e+4f 123.e+4l 0.123e+4 0.123e+4f 0.123e+4l .123e+4 .123e+4f .123e+4l // + Sign Power
  		
  		0x0.123p4  0x0.123p4f  0x0.123p4l  0x.123p4  0x.123p4f  0x.123p4l                // Hex Float Power
  		0x0.123p-4 0x0.123p-4f 0x0.123p-4l 0x.123p-4 0x.123p-4f 0x.123p-4l               // Hex Float - Sign Power
  		0x0.123p+4 0x0.123p+4f 0x0.123p+4l 0x.123p+4 0x.123p+4f 0x.123p+4l               // Hex Float + Sign Power
  
  		'a' 'A' '0' '%' ' '
  	);
  
  	std::string expressions = code(
  
  	if (a == 10)
  	{
  		vector[10].x += a == b ? 1 : a[i].y;
  	}
  	switch (vector[10].x)
  	{
  	case 1: break;
  	default: vector[10].y /= 10;
  	}
  	
  	
  	);
  
  	std::string declarations = code(
  
  		int Func();
  		
  
  
  	);
  };