
#expr SyntaxPatt <\<...\>>
{
	#script
		text = node.text;
		text = text.replace(/^\s*<|>\s*$/g, '').trim();
		text = text.replace(/\n\s*/g,  ' ');
		text = text.replace(/ {2,}/g,  ' ');
		text = '"'+SText(text, '"')+'"';
		return new Card('STRING', text);
	#end
}

module.exports = {

	"COMMENT"             : require("./comment.js")

	"Root"                : require("./root.js")

	"Block"               : require("./block.js")

	"StamBlock"           : <Block | Statement@:BlockStam>

	"Statement"           : <LabelStam |
							(	\{ → [JsonAssignExpr JsonExpr Block] |
								\[ → ArrayAssignExpr                 |
								#SUGAR(statement)                    |
								[Declaration Keyword MethodDecl LinkStam Comma]
							)\n (CLOSE → | &==[Expression] [SeleteLeft SeleteRight]@@SeleteStam | SeleteLeft@@SeleteStam | END∅∆1101)>

	"Expression"           : <[ function → FunctionExpr, class → Class, Ternary ] (&==[Access] (Params@@CallExpr | (=@@AssignExpr | ASSIGN@@AssignPatt) AssignRight∆1107))?>

	"Object"               : <CONST |
							[
								\@           → AtExpr,
								\[           → ArrayExpr,
								\(           → CompelExpr,
								\{           → JsonExpr,
								super        → SuperExpr,
								require      → RequireExpr
							] | VariableExpr | #SUGAR(expression)>

	"CONST"               : <REGEXP | STRING | TAG>
	"REGEXP"              : <[\/ \/=] → #CONCAT( \/=\\|\/...*\/\\|\/ [g i m y]*, , REGEXP CONST)>
	"STRING"              : <QUOTE → #CONCAT( , , STRING CONST)>
	"TAG"                 : <#+ [IDENTIFIER KEYWORD]>

	"Access"              : <Object (MemberExpr@~AccessExpr)*>
	"Value"               : <[@ this]?@@ThisExpr → Object (MemberExpr@~AccessExpr | ParamsExpr@~CallExpr)* SlicePatt?@~SliceExpr>
	"MemberExpr"    	  : <[ . → . [IDENTIFIER KEYWORD]∆1108, \[ → \\[ CommaExpr \\], :: → :: [IDENTIFIER KEYWORD]?]>
	"AtExpr"              : <@ [IDENTIFIER KEYWORD]?>
	"SuperExpr"           : <super (MemberExpr*)@:SuperMember Params?>
	"SlicePatt"           : <[∅ ]∅ | [∅ (Compute? : Compute?) ]∆1109∅>

	"JsonExpr"            : <\{∅ ( \}∅ | JsonItem (,?∅ JsonItem)* ,*∅ \}∆1123∅)>
	"JsonItem"            : <set→ SetterDecl | get→ GetterDecl | IDENTIFIER→ [+1, \(]→ MethodDecl | ([NameExpr NUMBER STRING] : Expression)@:AssignExpr>

	"ArrayExpr"           : <[∅ ]∅ | [∅ Expression (,?∅ Expression)* ,*∅ ]∆1124∅>
	"VariableExpr"        : <IDENTIFIER>
	"NameExpr"            : <IDENTIFIER | KEYWORD {id}!∆1006>

	"Declaration"         : <[
							var          → VarStam,
							let          → LetStam,
							const        → ConstStam,
							function     → FunctionDecl,
							class        → Class,
							import       → ImportStam,
							export       → ExportDecl,
							static       → StaticDecl,
							get          → GetterDecl,
							set          → SetterDecl,
							prototype    → ProtoDecl,
							property     → PropertyDecl,
							constructor  → ConstructorDecl]>

	"Keyword"             : <[
							return       → ReturnStam,
							break        → BreakStam,
							continue     → ContinueStam,
							throw        → ThrowStam,
							debugger     → DebuggerStam,
							if           → IfStam,
							while        → WhileStam,
							do           → DoWhileStam,
							with         → WithStam,
							try          → TryStam,
							switch       → SwitchStam,
							for          → ForStam,
							yield        → YieldStam]>

	// TODO: coming soon for support syntax  
	"YieldStam" : <yield Expression>
	"ImportStam": <import!∆1>
	// -----------------------------

	"Unary"               : <not Expression@@NotExpr | PREFIX Value@@PrefixExpr | new Value@@NewExpr | UNARY #Unary@@UnaryExpr | Value POSTFIX?@@PostfixExpr>

	"ComputeLv0"          : <Unary (PREC0 Unary@~ComputeExpr)*>
	"ComputeLv1"          : <ComputeLv0 (PREC1 ComputeLv0@~ComputeExpr)*>
	"ComputeLv2"          : <ComputeLv1 (PREC2 ComputeLv1@~ComputeExpr)*>
	"CompareLv3"          : <ComputeLv2 (PREC3 ComputeLv2@~CompareExpr)*>
	"Compare"             : <CompareLv3 (PREC4 CompareLv3@~CompareExpr)*>
	"Compute"             : <Compare (PREC5 Compare@~ComputeExpr)*>
	"Operate"             : <Compute (PREC6 [Keyword Assign Compute]@~LogicExpr)*>
	"Binary"              : <Assign | Operate>
	"Ternary"             : <Operate (\?@@TernaryExpr [Declaration Keyword Expression] (: [Declaration Keyword Expression])?)?>
	
	"Rest"                : <...?∅@@RestExpr IDENTIFIER>
	"AssignRight"         : <[ArrowExpr Expression]>
	"ArrayAssignExpr"     : <[∅ (Rest (,∅ Rest)*)@:ArrayPatt ]∅ = AssignRight>
	"JsonAssignExpr"      : <{∅ ((IDENTIFIER (\: IDENTIFIER)?)@?AssignExpr (,∅ (IDENTIFIER (\: IDENTIFIER)?)@?AssignExpr)*)@:JsonPatt }∅ = AssignRight>
	"Assign"              : <[ \[ → ArrayAssignExpr, \{ → JsonAssignExpr, Access (=@@AssignExpr | ASSIGN@@AssignPatt) AssignRight∆1107 ]>

	"ArgusItem"           : <[ ... → Rest, \[  → ArrayAssignExpr, \{  → JsonAssignExpr, VariableExpr (= AssignRight)?@@AssignExpr ]>
	"Argus"               : <ArgusItem (,∅ ArgusItem)*>
	"ArgusStam"           : <ArgusItem (,∅ ArgusItem)*>
	"ArgusExpr"           : <\(∅ ( \)∅ | ArgusItem (,∅ ArgusItem)* \)∅)>
	
	"ParamsGroup"         : <(AssignRight (, [\, \)]→)*) (,∅ AssignRight (, [\, \)]→)*)*>
	"ParamsExpr"          : <\(∅ ( \)∅ | ,* ParamsGroup \)∆1104∅)>
	"Params"              : <ParamsExpr | [--1, BLANK]→ [--2, !END]→ ParamsGroup@:ParamsExpr>

	"CommaExpr"           : <Expression (,∅ Expression∆1125)*>
	"Comma"               : <Expression (,∅ Expression∆1125)*@@CommaExpr>
	"CompelExpr"          : <(∅ CommaExpr∆1126 )∅>
	"LabelStam"           : <IDENTIFIER : Statement>
	// "SeleteLeft"          : <(<- | if [--1, BLANK !HEAD]→) Comma∆1127>
	"SeleteLeft"          : <(<- | if\n) Comma∆1127>
	"SeleteRight"         : <[&& || and or ->] Statement∆1127>
	"LinkStam"            : <Access (..∅ (Access Params?)@:LinkPatt)+>

	// 
	"ArrowExpr"          : <(ArgusExpr | IDENTIFIER@:ArgusExpr) =>∅ ({→ [JsonExpr Block] | ReturnStam | ThrowStam | Expression)>
	
	"VarStam"             : <var∅      ArgusStam∆1007>
	"LetStam"             : <let∅      ArgusStam∆1009>
	"ConstStam"           : <const∅    ArgusStam∆1010>

	"ReturnStam"          : <return\n   CommaExpr?>
	"BreakStam"           : <break\n    IDENTIFIER?>
	"ContinueStam"        : <continue\n IDENTIFIER?>
	"ThrowStam"           : <throw\n    CommaExpr?>
	"RequireExpr"         : <require    Params>
	"DebuggerStam"        : <debugger>
	
	"FunctionExpr"        : <function \*?@@GeneratorExpr  #NameExpr(id)?@@FunctionDecl ArgusExpr Block>
	"FunctionDecl"        : <function \*?@@GeneratorDecl  #NameExpr(id)∆1024 ArgusExpr Block>
	"MethodDecl"          : <NameExpr     ArgusExpr [{ :]→ Block∆1106>
	"Class"               : <class@@ClassExpr (extends! → #NameExpr(id)?@@ClassDecl) (extends Params∆1021)?@:ExtendsExpr Block>
	"GetterDecl"          : <get∅        NameExpr ArgusExpr?@!ArgusExpr Block>
	"SetterDecl"          : <set∅        NameExpr ArgusExpr Block>
	"StaticDecl"          : <static∅     [MethodDecl ArgusStam]>
	"ProtoDecl"           : <prototype∅  [MethodDecl ArgusStam]>
	"PropertyDecl"        : <property∅   [MethodDecl ArgusStam]>
	"ConstructorDecl"     : <constructor@:NameExpr  ArgusExpr [{ :]→ Block∆1106>
	"ExportDecl"          : <export∅ (default [MethodDecl Declaration Expression] | [MethodDecl Declaration ArgusStam])∆1011>
	
	"If"                  : <if ConditionExpr StamBlock∆1012@@IfPatt>
	"Else"                : <else@@ElsePatt (if∅ ConditionExpr@@ElseIfPatt | ConditionExpr [{ :]→@@ElseIfPatt)? StamBlock∆1019>
	"Try"                 : <try     StamBlock∆1016@@TryPatt>
	"Catch"           	  : <catch   ConditionExpr StamBlock@@CatchPatt>
	"Finally"             : <finally StamBlock@@FinallyPatt>
	"WhileStam"           : <while   ConditionExpr StamBlock∆1013>
	"WithStam"            : <with    ConditionExpr StamBlock∆1014>
	"SwitchStam"          : <switch  ConditionExpr (\:∅ #Case(indent)* | {∅ #Case* }∆1110∅)@:BlockNode∆1017>
	"Case"                : <(case@@CaseStam CommaExpr | default@@DefaultStam) \:∆1020∅ ({indent} #Block(indent, case, default) | {indent}! #Block(brace, case, default))?>
	
	"ConditionExpr"       : <Comma &==[CompelExpr]?@@=ConditionExpr>

	"ForStam"             : <for ForCondition∆1022 StamBlock∆1106>
	"ForCondition"        : require('./for.js')
	"IfStam"              : <If  (#INDENT Else)*>
	"TryStam"             : <Try (#INDENT Catch)? (#INDENT Finally)?>
	"DoWhileStam"         : <do  StamBlock∆1015 (#INDENT while ConditionExpr)?>
}