diff --git a/spec/parser_spec.lua b/spec/parser_spec.lua index 1a1bc1d..4ce62b5 100644 --- a/spec/parser_spec.lua +++ b/spec/parser_spec.lua @@ -866,8 +866,8 @@ describe("Titan parser", function() end) it("does not allow parentheses in the LHS of an assignment", function() - assert_statements_syntax_error([[ local (x) = 42 ]], "DeclLocal") - assert_statements_syntax_error([[ (x) = 42 ]], "ExpAssign") + assert_statements_syntax_error([[ local (xyz) = 42 ]], "DeclLocal") + assert_statements_syntax_error([[ (xzy) = 42 ]], "ExpAssignPred") end) it("does not allow identifiers that are type names", function() @@ -931,7 +931,8 @@ describe("Titan parser", function() ]], "AssignVar") assert_program_syntax_error([[ - x = + x = + local y = 3 ]], "ExpVarDec") assert_program_syntax_error([[ @@ -962,12 +963,12 @@ describe("Titan parser", function() assert_program_syntax_error([[ function foo (a:int, ) : int end - ]], "DeclParList") + ]], "ParamList") assert_program_syntax_error([[ function foo (a: ) : int end - ]], "TypeDecl") + ]], "TypeParam") assert_type_syntax_error([[ {} ]], "TypeType") @@ -980,6 +981,8 @@ describe("Titan parser", function() assert_type_syntax_error([[ (a, b) -> = nil ]], "TypeReturnTypes") + assert_type_syntax_error([[ (a, b) b ]], "Err_037") + assert_type_syntax_error([[ foo. ]], "QualName") assert_program_syntax_error([[ diff --git a/titan-compiler/annotatedTitan.txt b/titan-compiler/annotatedTitan.txt new file mode 100644 index 0000000..fe887ea --- /dev/null +++ b/titan-compiler/annotatedTitan.txt @@ -0,0 +1,136 @@ +program <- SKIP* (toplevelfunc / toplevelvar / toplevelrecord / import / foreign)* !. +toplevelfunc <- localopt 'function' [NAME]^Err_001 ['(']^Err_002 paramlist [')']^Err_003 rettypeopt block ['end']^Err_004 +toplevelvar <- localopt decl ['=']^Err_005 [exp]^Err_006 +toplevelrecord <- 'record' [NAME]^Err_007 [recordfields]^Err_008 ['end']^Err_009 +localopt <- 'local'? +import <- 'local' [NAME]^Err_010 ['=']^Err_011 ['import']^Err_012 ['(' [STRINGLIT]^Err_013 [')']^Err_014 / STRINGLIT]^Err_015 +foreign <- 'local' [NAME]^Err_016 ['=']^Err_017 ['foreign']^Err_018 ['(' [STRINGLIT]^Err_019 [')']^Err_020 / STRINGLIT]^Err_021 +rettypeopt <- (':' [rettype]^Err_022)? +paramlist <- (param (',' [param]^Err_023)*)? +param <- NAME [':']^Err_024 [type]^Err_025 +decl <- NAME (':' [type]^Err_026)? +decllist <- decl (',' [decl]^Err_027)* +simpletype <- 'nil' / 'boolean' / 'integer' / 'float' / 'string' / 'value' / NAME / '{' [type]^Err_028 ['}']^Err_029 +typelist <- '(' (type (',' [type]^Err_030)*)? [')']^Err_031 +rettype <- typelist '->' rettype / simpletype '->' rettype / typelist / simpletype +type <- typelist ['->']^Err_032 [rettype]^Err_033 / simpletype '->' rettype / simpletype +recordfields <- recordfield+ +recordfield <- NAME [':']^Err_034 [type]^Err_035 ';'? +block <- statement* returnstat? +statement <- ';' / 'do' block ['end']^Err_036 / 'while' [exp]^Err_037 ['do']^Err_038 block ['end']^Err_039 / 'repeat' block ['until']^Err_040 [exp]^Err_041 / 'if' [exp]^Err_042 ['then']^Err_043 block elseifstats elseopt ['end']^Err_044 / 'for' [decl]^Err_045 ['=']^Err_046 [exp]^Err_047 [',']^Err_048 [exp]^Err_049 (',' [exp]^Err_050)? ['do']^Err_051 block ['end']^Err_052 / 'local' [decllist]^Err_053 ['=']^Err_054 [explist]^Err_055 / varlist '=' explist / suffixedexp +elseifstats <- elseifstat* +elseifstat <- 'elseif' [exp]^Err_056 ['then']^Err_057 block +elseopt <- ('else' block)? +returnstat <- 'return' explist? ';'? +exp <- e1 +e1 <- e2 ('or' [e2]^Err_058)* +e2 <- e3 ('and' [e3]^Err_059)* +e3 <- e4 (('==' / '~=' / '<' / '>' / '<=' / '>=') [e4]^Err_060)* +e4 <- e5 ('|' [e5]^Err_061)* +e5 <- e6 ('~' [e6]^Err_062)* +e6 <- e7 ('&' [e7]^Err_063)* +e7 <- e8 (('<<' / '>>') [e8]^Err_064)* +e8 <- e9 ('..' [e8]^Err_065)? +e9 <- e10 (('+' / '-') [e10]^Err_066)* +e10 <- e11 (('*' / '%%' / '/' / '//') [e11]^Err_067)* +e11 <- ('not' / '#' / '-' / '~')* e12 +e12 <- castexp ('^' [e11]^Err_068)? +suffixedexp <- prefixexp expsuffix+ +expsuffix <- funcargs / ':' [NAME]^Err_069 [funcargs]^Err_070 / '[' [exp]^Err_071 [']']^Err_072 / '.' [NAME]^Err_073 +prefixexp <- NAME / '(' [exp]^Err_074 [')']^Err_075 +castexp <- simpleexp 'as' type / simpleexp +simpleexp <- 'nil' / 'false' / 'true' / NUMBER / STRINGLIT / initlist / suffixedexp / prefixexp +var <- suffixedexp / NAME !expsuffix +varlist <- var (',' [var]^Err_076)* +funcargs <- '(' explist? [')']^Err_077 / initlist / STRINGLIT +explist <- exp (',' [exp]^Err_078)* +initlist <- '{' fieldlist? ['}']^Err_079 +fieldlist <- field (fieldsep field)* fieldsep? +field <- (NAME '=')? exp +fieldsep <- ';' / ',' +STRINGLIT <- '"' (!'"' .)* ['"']^Err_080 +RESERVED <- 'repeat' +NAME <- !RESERVED 'X' ('a' / 'b' / 'c' / NUMBER)* +NUMBER <- ('0' / '1' / '2' / '3' / '4' / '5' / '6' / '7' / '8' / '9')+ +SKIP <- ' ' +Err_001 <- (!'(' .)* +Err_002 <- (!('X' / ')') .)* +Err_003 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / 'X' / ';' / ':' / '(') .)* +Err_004 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_005 <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / 'X' / '9' / '8' / '7' / '6' / '5' / '4' / '3' / '2' / '1' / '0' / '-' / '(' / '#' / '"') .)* +Err_006 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_007 <- (!'X' .)* +Err_008 <- (!'end' .)* +Err_009 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_010 <- (!'=' .)* +Err_011 <- (!'import' .)* +Err_012 <- (!('(' / '"') .)* +Err_013 <- (!')' .)* +Err_014 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_015 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_016 <- (!'=' .)* +Err_017 <- (!'foreign' .)* +Err_018 <- (!('(' / '"') .)* +Err_019 <- (!')' .)* +Err_020 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_021 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_022 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / 'X' / ';' / '(') .)* +Err_023 <- (!')' .)* +Err_024 <- (!('{' / 'value' / 'string' / 'nil' / 'integer' / 'float' / 'boolean' / 'X' / '(') .)* +Err_025 <- (!(',' / ')') .)* +Err_026 <- (!('=' / ',') .)* +Err_027 <- (!'=' .)* +Err_028 <- (!'}' .)* +Err_029 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / '^' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / '//' / '/' / '..' / '->' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$') .)* +Err_030 <- (!')' .)* +Err_031 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / '^' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / '//' / '/' / '..' / '->' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$') .)* +Err_032 <- (!('{' / 'value' / 'string' / 'nil' / 'integer' / 'float' / 'boolean' / 'X' / '(') .)* +Err_033 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / '^' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / '//' / '/' / '..' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$') .)* +Err_034 <- (!('{' / 'value' / 'string' / 'nil' / 'integer' / 'float' / 'boolean' / 'X' / '(') .)* +Err_035 <- (!('end' / 'X' / ';') .)* +Err_036 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_037 <- (!'do' .)* +Err_038 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / 'X' / ';' / '(') .)* +Err_039 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_040 <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / 'X' / '9' / '8' / '7' / '6' / '5' / '4' / '3' / '2' / '1' / '0' / '-' / '(' / '#' / '"') .)* +Err_041 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_042 <- (!'then' .)* +Err_043 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_044 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_045 <- (!'=' .)* +Err_046 <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / 'X' / '9' / '8' / '7' / '6' / '5' / '4' / '3' / '2' / '1' / '0' / '-' / '(' / '#' / '"') .)* +Err_047 <- (!',' .)* +Err_048 <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / 'X' / '9' / '8' / '7' / '6' / '5' / '4' / '3' / '2' / '1' / '0' / '-' / '(' / '#' / '"') .)* +Err_049 <- (!('do' / ',') .)* +Err_050 <- (!'do' .)* +Err_051 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / 'X' / ';' / '(') .)* +Err_052 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_053 <- (!'=' .)* +Err_054 <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / 'X' / '9' / '8' / '7' / '6' / '5' / '4' / '3' / '2' / '1' / '0' / '-' / '(' / '#' / '"') .)* +Err_055 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_056 <- (!'then' .)* +Err_057 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_058 <- (!('}' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / ']' / 'X' / ';' / ',' / ')' / '(' / '$') .)* +Err_059 <- (!('}' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / ']' / 'X' / ';' / ',' / ')' / '(' / '$') .)* +Err_060 <- (!('}' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / ';' / ',' / ')' / '(' / '$') .)* +Err_061 <- (!('~=' / '}' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>=' / '>' / '==' / '<=' / '<' / ';' / ',' / ')' / '(' / '$') .)* +Err_062 <- (!('~=' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>=' / '>' / '==' / '<=' / '<' / ';' / ',' / ')' / '(' / '$') .)* +Err_063 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>=' / '>' / '==' / '<=' / '<' / ';' / ',' / ')' / '(' / '$') .)* +Err_064 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>=' / '>' / '==' / '<=' / '<' / ';' / ',' / ')' / '(' / '&' / '$') .)* +Err_065 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / ',' / ')' / '(' / '&' / '$') .)* +Err_066 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / '..' / ',' / ')' / '(' / '&' / '$') .)* +Err_067 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / '..' / '-' / ',' / '+' / ')' / '(' / '&' / '$') .)* +Err_068 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / '//' / '/' / '..' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$') .)* +Err_069 <- (!('{' / '(' / '"') .)* +Err_070 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_071 <- (!']' .)* +Err_072 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_073 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_074 <- (!')' .)* +Err_075 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_076 <- (!'=' .)* +Err_077 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_078 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / ')' / '(') .)* +Err_079 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_080 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* + diff --git a/titan-compiler/annotatedTitanMet.txt b/titan-compiler/annotatedTitanMet.txt new file mode 100644 index 0000000..0a5037e --- /dev/null +++ b/titan-compiler/annotatedTitanMet.txt @@ -0,0 +1,145 @@ +program <- SKIP* (method / toplevelfunc / toplevelvar / toplevelrecord / import / foreign)* !. +method <- 'function' [NAME]^Err_001 [':']^Err_002 [NAME]^Err_003 ['(']^Err_004 paramlist [')']^Err_005 rettypeopt block ['end']^Err_006 +toplevelfunc <- localopt 'function' [NAME]^Err_007 ['(']^Err_008 paramlist [')']^Err_009 rettypeopt block ['end']^Err_010 +toplevelvar <- localopt decl ['=']^Err_011 !('import' / 'foreign') [exp]^Err_012 +toplevelrecord <- 'record' [NAME]^Err_013 recordfields ['end']^Err_014 +localopt <- 'local'? +import <- 'local' [NAME]^Err_015 ['=']^Err_016 !'foreign' ['import']^Err_017 ['(' [STRINGLIT]^Err_018 [')']^Err_019 / STRINGLIT]^Err_020 +foreign <- 'local' [NAME]^Err_021 ['=']^Err_022 ['foreign']^Err_023 ['(' [STRINGLIT]^Err_024 [')']^Err_025 / STRINGLIT]^Err_026 +rettypeopt <- (':' [rettype]^Err_027)? +paramlist <- (param (',' [param]^Err_028)*)? +param <- NAME [':']^Err_029 [type]^Err_030 +decl <- NAME (':' [type]^Err_031)? +decllist <- decl (',' [decl]^Err_032)* +simpletype <- 'nil' / 'boolean' / 'integer' / 'float' / 'string' / 'value' / NAME '.' NAME / NAME / '{' type ':' type '}' / '{' [type]^Err_033 ['}']^Err_034 +typelist <- '(' (type (',' [type]^Err_035)*)? [')']^Err_036 +rettype <- typelist '->' rettype / simpletype '->' rettype / typelist / simpletype +type <- typelist ['->']^Err_037 [rettype]^Err_038 / simpletype '->' rettype / simpletype +recordfields <- recordfield* +recordfield <- NAME [':']^Err_039 [type]^Err_040 ';'? +block <- statement* returnstat? +statement <- ';' / 'do' block ['end']^Err_041 / 'while' [exp]^Err_042 ['do']^Err_043 block ['end']^Err_044 / 'repeat' block ['until']^Err_045 [exp]^Err_046 / 'if' [exp]^Err_047 ['then']^Err_048 block elseifstats elseopt ['end']^Err_049 / 'for' [decl]^Err_050 ['=']^Err_051 [exp]^Err_052 [',']^Err_053 [exp]^Err_054 (',' [exp]^Err_055)? ['do']^Err_056 block ['end']^Err_057 / 'local' [decllist]^Err_058 ['=']^Err_059 [explist]^Err_060 / varlist '=' explist / suffixedexp +elseifstats <- elseifstat* +elseifstat <- 'elseif' [exp]^Err_061 ['then']^Err_062 block +elseopt <- ('else' block)? +returnstat <- 'return' explist? ';'? +exp <- e1 +e1 <- e2 ('or' [e2]^Err_063)* +e2 <- e3 ('and' [e3]^Err_064)* +e3 <- e4 (('==' / '~=' / '<' / '>' / '<=' / '>=') [e4]^Err_065)* +e4 <- e5 ('|' [e5]^Err_066)* +e5 <- e6 ('~' [e6]^Err_067)* +e6 <- e7 ('&' [e7]^Err_068)* +e7 <- e8 (('<<' / '>>') [e8]^Err_069)* +e8 <- e9 ('..' [e8]^Err_070)? +e9 <- e10 (('+' / '-') [e10]^Err_071)* +e10 <- e11 (('*' / '%%' / '/' / '//') [e11]^Err_072)* +e11 <- ('not' / '#' / '-' / '~')* e12 +e12 <- castexp ('^' [e11]^Err_073)? +suffixedexp <- prefixexp expsuffix+ +expsuffix <- funcargs / ':' [NAME]^Err_074 [funcargs]^Err_075 / '[' [exp]^Err_076 [']']^Err_077 / '.' [NAME]^Err_078 +prefixexp <- NAME / '(' [exp]^Err_079 [')']^Err_080 +castexp <- simpleexp 'as' type / simpleexp +simpleexp <- 'nil' / 'false' / 'true' / NUMBER / STRINGLIT / initlist / suffixedexp / prefixexp +var <- suffixedexp / NAME !expsuffix +varlist <- var (',' [var]^Err_081)* +funcargs <- '(' explist? [')']^Err_082 / initlist / STRINGLIT +explist <- exp (',' [exp]^Err_083)* +initlist <- '{' fieldlist? ['}']^Err_084 +fieldlist <- field (fieldsep field)* fieldsep? +field <- (key '=')? exp +key <- NAME / '[' [exp]^Err_085 [']']^Err_086 +fieldsep <- ';' / ',' +STRINGLIT <- '"' (!'"' .)* ['"']^Err_087 +RESERVED <- 'repeat' +NAME <- !RESERVED 'X' ('a' / 'b' / 'c' / NUMBER)* +NUMBER <- ('0' / '1' / '2' / '3' / '4' / '5' / '6' / '7' / '8' / '9')+ +SKIP <- ' ' +Err_001 <- (!':' .)* +Err_002 <- (!'X' .)* +Err_003 <- (!'(' .)* +Err_004 <- (!('X' / ')') .)* +Err_005 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / 'X' / ';' / ':' / '(') .)* +Err_006 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_007 <- (!'(' .)* +Err_008 <- (!('X' / ')') .)* +Err_009 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / 'X' / ';' / ':' / '(') .)* +Err_010 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_011 <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / 'X' / '9' / '8' / '7' / '6' / '5' / '4' / '3' / '2' / '1' / '0' / '-' / '(' / '#' / '"') .)* +Err_012 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_013 <- (!('end' / 'X') .)* +Err_014 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_015 <- (!'=' .)* +Err_016 <- (!'import' .)* +Err_017 <- (!('(' / '"') .)* +Err_018 <- (!')' .)* +Err_019 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_020 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_021 <- (!'=' .)* +Err_022 <- (!'foreign' .)* +Err_023 <- (!('(' / '"') .)* +Err_024 <- (!')' .)* +Err_025 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_026 <- (!('record' / 'local' / 'function' / 'X' / '$') .)* +Err_027 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / 'X' / ';' / '(') .)* +Err_028 <- (!')' .)* +Err_029 <- (!('{' / 'value' / 'string' / 'nil' / 'integer' / 'float' / 'boolean' / 'X' / '(') .)* +Err_030 <- (!(',' / ')') .)* +Err_031 <- (!('=' / ',') .)* +Err_032 <- (!'=' .)* +Err_033 <- (!'}' .)* +Err_034 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / '^' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '->' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$') .)* +Err_035 <- (!')' .)* +Err_036 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / '^' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '->' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$') .)* +Err_037 <- (!('{' / 'value' / 'string' / 'nil' / 'integer' / 'float' / 'boolean' / 'X' / '(') .)* +Err_038 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / '^' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$') .)* +Err_039 <- (!('{' / 'value' / 'string' / 'nil' / 'integer' / 'float' / 'boolean' / 'X' / '(') .)* +Err_040 <- (!('end' / 'X' / ';') .)* +Err_041 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_042 <- (!'do' .)* +Err_043 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / 'X' / ';' / '(') .)* +Err_044 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_045 <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / 'X' / '9' / '8' / '7' / '6' / '5' / '4' / '3' / '2' / '1' / '0' / '-' / '(' / '#' / '"') .)* +Err_046 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_047 <- (!'then' .)* +Err_048 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_049 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_050 <- (!'=' .)* +Err_051 <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / 'X' / '9' / '8' / '7' / '6' / '5' / '4' / '3' / '2' / '1' / '0' / '-' / '(' / '#' / '"') .)* +Err_052 <- (!',' .)* +Err_053 <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / 'X' / '9' / '8' / '7' / '6' / '5' / '4' / '3' / '2' / '1' / '0' / '-' / '(' / '#' / '"') .)* +Err_054 <- (!('do' / ',') .)* +Err_055 <- (!'do' .)* +Err_056 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / 'X' / ';' / '(') .)* +Err_057 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_058 <- (!'=' .)* +Err_059 <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / 'X' / '9' / '8' / '7' / '6' / '5' / '4' / '3' / '2' / '1' / '0' / '-' / '(' / '#' / '"') .)* +Err_060 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_061 <- (!'then' .)* +Err_062 <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / '(') .)* +Err_063 <- (!('}' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / ']' / 'X' / ';' / ',' / ')' / '(' / '$') .)* +Err_064 <- (!('}' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / ']' / 'X' / ';' / ',' / ')' / '(' / '$') .)* +Err_065 <- (!('}' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / ';' / ',' / ')' / '(' / '$') .)* +Err_066 <- (!('~=' / '}' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>=' / '>' / '==' / '<=' / '<' / ';' / ',' / ')' / '(' / '$') .)* +Err_067 <- (!('~=' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>=' / '>' / '==' / '<=' / '<' / ';' / ',' / ')' / '(' / '$') .)* +Err_068 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>=' / '>' / '==' / '<=' / '<' / ';' / ',' / ')' / '(' / '$') .)* +Err_069 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>=' / '>' / '==' / '<=' / '<' / ';' / ',' / ')' / '(' / '&' / '$') .)* +Err_070 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / ',' / ')' / '(' / '&' / '$') .)* +Err_071 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / '..' / ',' / ')' / '(' / '&' / '$') .)* +Err_072 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / '..' / '-' / ',' / '+' / ')' / '(' / '&' / '$') .)* +Err_073 <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / 'X' / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / '//' / '/' / '..' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$') .)* +Err_074 <- (!('{' / '(' / '"') .)* +Err_075 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_076 <- (!']' .)* +Err_077 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_078 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_079 <- (!')' .)* +Err_080 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_081 <- (!'=' .)* +Err_082 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_083 <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'X' / ';' / ')' / '(') .)* +Err_084 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* +Err_085 <- (!']' .)* +Err_086 <- (!'=' .)* +Err_087 <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / 'X' / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / '$' / '"') .)* + diff --git a/titan-compiler/lexer.lua b/titan-compiler/lexer.lua index 95f8616..e6a5ca8 100644 --- a/titan-compiler/lexer.lua +++ b/titan-compiler/lexer.lua @@ -180,7 +180,9 @@ for _, keyword in ipairs(keywords) do end lexer.NAME = Cmt(C(possiblename), function(_, pos, s) + --print('lexer', _, pos, s, is_keyword[s]) if not is_keyword[s] then + --print("lexer will return ", s) return pos, s else return false diff --git a/titan-compiler/parser.lua b/titan-compiler/parser.lua index 3c2576e..e72a671 100644 --- a/titan-compiler/parser.lua +++ b/titan-compiler/parser.lua @@ -18,6 +18,7 @@ local THIS_FILENAME = nil -- local defs = {} +local synerr for tokname, tokpat in pairs(lexer) do defs[tokname] = tokpat @@ -27,6 +28,25 @@ for tag, cons in pairs(ast) do defs[tag] = cons end +defs['adderror'] = function (pos, lab) + table.insert(synerr, { pos = pos, lab = lab }) + return +end + +defs['defaultInt'] = 52 +defs['defaultInt2'] = function () return 52 end +defs['defaultMethName'] = 'm42' +defs['defaultQualName'] = 'q42' +defs['defaultFuncName'] = 'f42' +defs['defaultRecName'] = 'rec42' +defs['defaultFieldRec'] = function() return 'field42' end +defs['defaultImportName'] = 'imp42' +defs['defaultStringImportName'] = 'mod42' +defs['defaultForeignName'] = 'foreign42' +defs['defaultDeclName'] = 'dec42' +defs['defaultColonName'] = 'col42' +defs['defaultDotName'] = 'dot42' + function defs.get_loc(s, pos) return true, location.from_pos(THIS_FILENAME, s, pos) end @@ -76,6 +96,9 @@ function defs.nil_exp(pos--[[, s ]]) end function defs.number_exp(pos, n) + --print("number_exp", pos, n, math.type(n)) + --assert(n ~= 52) + --assert(n ~= '52') if math.type(n) == "integer" then return ast.ExpInteger(pos, n) elseif math.type(n) == "float" then @@ -228,7 +251,7 @@ local grammar = re.compile([[ / toplevelvar / toplevelrecord / import - / foreign )* |} !. + / foreign )* |} (!. / %{EndInput}) method <- (P FUNCTION NAME COLON NAME^NameMethod LPAREN^LParPList paramlist RPAREN^RParPList @@ -260,10 +283,10 @@ local grammar = re.compile([[ rettypeopt <- (P (COLON rettype^TypeFunc)?) -> rettypeopt - paramlist <- {| (param (COMMA param^DeclParList)*)? |} -- produces {Decl} + paramlist <- {| (param (COMMA param^ParamList)*)? |} -- produces {Decl} param <- (P NAME COLON^ParamSemicolon - type^TypeDecl) -> Decl + type^TypeParam) -> Decl decl <- (P NAME (COLON type^TypeDecl)? -> opt) -> Decl @@ -295,7 +318,7 @@ local grammar = re.compile([[ / typelist / {| simpletype |} - type <- (P typelist RARROW + type <- (P typelist RARROW^Err_037 rettype^TypeReturnTypes) -> TypeFunction / (P {| simpletype |} RARROW rettype^TypeReturnTypes) -> TypeFunction @@ -325,7 +348,7 @@ local grammar = re.compile([[ explist^ExpLocal) -> StatDecl / (P varlist ASSIGN^AssignAssign explist^ExpAssign) -> StatAssign - / &(exp ASSIGN) %{ExpAssign} + / &(exp ASSIGN) %{ExpAssignPred} / (P (suffixedexp => exp_is_call)) -> StatCall / &exp %{ExpStat} @@ -359,12 +382,12 @@ local grammar = re.compile([[ e4 <- (P {| e5 (op4 e5^OpExp)* |}) -> fold_binop_left e5 <- (P {| e6 (op5 e6^OpExp)* |}) -> fold_binop_left e6 <- (P {| e7 (op6 e7^OpExp)* |}) -> fold_binop_left - e7 <- (P {| e8 (op7 e8^OpExp)* |}) -> fold_binop_left - e8 <- (P e9 (op8 e8^OpExp)?) -> binop_concat - e9 <- (P {| e10 (op9 e10^OpExp)* |}) -> fold_binop_left + e7 <- (P {| e8 (op7 e8^OpExp)* |}) -> fold_binop_left + e8 <- (P e9 (op8 e8^OpExp)?) -> binop_concat + e9 <- (P {| e10 (op9 e10^OpExp)* |}) -> fold_binop_left e10 <- (P {| e11 (op10 e11^OpExp)* |}) -> fold_binop_left e11 <- (P {| unop* |} e12) -> fold_unops - e12 <- (P castexp (op12 e11^OpExp)?) -> binop_right + e12 <- (P castexp (op12 e11^OpExp)?) -> binop_right suffixedexp <- (prefixexp {| expsuffix+ |}) -> fold_suffixes @@ -416,7 +439,7 @@ local grammar = re.compile([[ key <- NAME / LBRACKET exp^ExpExpSuf - RBRACKET^RBracketExpSuf + RBRACKET^RBracketExpKey fieldsep <- SEMICOLON / COMMA @@ -509,21 +532,333 @@ local grammar = re.compile([[ NEG <- SUB BNEG <- BXOR + + NAMEREC <- [a-zA-Z_][a-zA-Z0-9_]* + + eatTk <- NAMEREC / AND / BREAK / DO / ELSEIF / END / FALSE / FOR / FUNCTION / GOTO / IF / IN / LOCAL / NIL / NOT / OR / RECORD / REPEAT / RETURN / THEN / TRUE / UNTIL / WHILE / IMPORT / AS / FOREIGN / BOOLEAN / INTEGER / FLOAT / STRING / VALUE / . + + --Err_003: + NameMethod <- ({} '' -> 'NameMethod') -> adderror NameMethodRec ('' -> defaultMethName) + NameMethodRec <- (!'(' eatTk)* + + --Err_004: not in parser_spec + LParPList <- ({} '' -> 'LParPList') -> adderror LParPListRec + LParPListRec <- (!(NAME / ')') eatTk)* + + --Err_005: not in parser_spec + RParPList <- ({} '' -> 'RParPList') -> adderror RParPListRec + RParPListRec <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / NAME / ';' / ':' / '(') eatTk)* + + --Err_006: + EndFunc <- ({} '' -> 'EndFunc') -> adderror EndFuncRec + EndFuncRec <- (!('record' / 'local' / 'function' / NAME / !.) eatTk)* + + --Err_007: use NameMethodRec (Err_003) + NameFunc <- ({} '' -> 'NameFunc') -> adderror NameMethodRec ('' -> defaultFuncName) + + --Err_008, Err_009, and Err_010 refer, respectively, to labels + --LParPList, RParPlist, and EndFunc, which were also used by rule 'method' + --and have the same recovery set + + --Err_011: + AssignVar <- ({} '' -> 'AssignVar') -> adderror AssignVarRec + AssignVarRec <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / NAME / NUMBER / '-' / '(' / '#' / STRINGLIT) eatTk)* + + --Err_012: use EndFuncRec (Err_006) + ExpVarDec <- ({} '' -> 'ExpVarDec') -> adderror EndFuncRec (P '' -> defaultInt2) -> number_exp + + --Err_013: Problem: the recovery pattern will not work well, because we reach this label when 'NAME' fails to match (error) + NameRecord <- ({} '' -> 'NameRecord') -> adderror NameRecordRec ('' -> defaultRecName) + NameRecordRec <- (!('end' / NAME) eatTk)* + + --Err_014: use EndFuncRec (Err_006) + EndRecord <- ({} '' -> 'EndRecord') -> adderror EndFuncRec + + --Err_015: + NameImport <- ({} '' -> 'NameImport') -> adderror NameImportRec ('' -> defaultImportName) + NameImportRec <- (!'=' eatTk)* + + + --Err_016: not in parser_spec + AssignImport <- ({} '' -> 'AssignImport') -> adderror AssignImportRec + AssignImportRec <- (!'import' eatTk)* + + --Err_017: not in parser_spec + ImportImport <- ({} '' -> 'ImportImport') -> adderror ImportImportRec + ImportImportRec <- (!('(' / STRINGLIT) eatTk)* + + --Err_018: + StringLParImport <- ({} '' -> 'StringLParImport') -> adderror StringLParImportRec ('' -> defaultStringImportName) + StringLParImportRec <- (!')' eatTk)* + + --Err_019: use EndFuncRec (Err_006) + RParImport <- ({} '' -> 'RParImport') -> adderror EndFuncRec + + --Err_020: use EndFuncRec (Err_006) + StringImport <- ({} '' -> 'StringImport') -> adderror EndFuncRec ('' -> defaultStringImportName) + + --Err_021, Err_022, Err_023, Err_024, Err_025, Err_026: not in parser_spec + --There are no specific labels for 'foreign'. The same labels from 'import' are used + + --Err_027: TypeFunc + TypeFunc <- ({} '' -> 'TypeFunc') -> adderror TypeFuncRec (P '') -> TypeInteger + TypeFuncRec <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'do' / NAME / ';' / '(') eatTk)* + + --Err_028: DeclParList -> ParamList + --The label DeclParList was used by rules decllist and paramlist. I am using distinct labels for each now, + --because they have different recovery expressions. (It seems ',' should be in both recovery expressions. TODO: check 'first.lua') + -- use StringLParImportRec (Err_018) + ParamList <- ({} '' -> 'ParamList') -> adderror StringLParImportRec + + --Err_029: + ParamSemicolon <- ({} '' -> 'ParamSemicolon') -> adderror ParamSemicolonRec + ParamSemicolonRec <- (!('{' / 'value' / 'string' / 'nil' / 'integer' / 'float' / 'boolean' / NAME / '(') eatTk)* + + --Err_030: TypeDecl -> TypeParam + --Same reasoning of DeclParList + TypeParam <- ({} '' -> 'TypeParam') -> adderror TypeParamRec (P '') -> TypeInteger + TypeParamRec <- (!(',' / ')') eatTk)* + + --Err_031: not in parser_spec + TypeDecl <- ({} '' -> 'TypeDecl') -> adderror TypeDeclRec (P '') -> TypeInteger + TypeDeclRec <- (!('=' / ',') eatTk)* + + --Err_032: use NameImportRec (Err_015) + DeclParList <- ({} '' -> 'DeclParList') -> adderror NameImportRec + + --Err_XXX: the algorithm did not insert the label corresponding to QualName in rule 'simpletype' + -- use RCurlyTypeRec (Err_034) + QualName <- ({} '' -> 'QualName') -> adderror RCurlyTypeRec ('' -> defaultQualName) + + --Err_XXX: The algorithm did not insert the first labels TypeType and RCurlyType in the penultimate + --alternative of 'simpletype', just in the last one. I am using an union of what be the recovery set + --of all labels TypeType + --Err_033: + TypeType <- ({} '' -> 'TypeType') -> adderror TypeTypeRec (P '') -> TypeInteger + TypeTypeRec <- (!('}' / '.') eatTk)* + + --Err_XXX: See above. Both labels RCurlyType have the same recovery set + --Err_034: + RCurlyType <- ({} '' -> 'RCurlyType') -> adderror RCurlyTypeRec + RCurlyTypeRec <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / '^' / ']' / NAME / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '->' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / !.) eatTk)* + + --Err_035: use StringLParImportRec (Err_018) + TypelistType <- ({} '' -> 'TypelistType') -> adderror StringLParImportRec + + --Err_036: use RCurlyTypeRec (Err_034) + RParenTypelist <- ({} '' -> 'RParenTypelist') -> adderror RCurlyTypeRec + + --Err_XXX: the algorithm did not insert the two labels corresponding to TypeReturnTypes in rule 'rettype' + --Label TypeReturnTypes is also used in rule 'type' and its first occurrence in this rule corresponds to Err_038 + --We use recovery expression of Err_038 for all occurrences of TypeReturnTypes + + --Err_037: The original grammar does not have this label + -- Use ParamSemicolonRec (Err_029) + Err_037 <- ({} '' -> 'Err_037') -> adderror ParamSemicolonRec + + --Err_038: The original grammar used TypeReturnTypes here, but the recovery set is different so I introduced label TypeReturnTypes + --TODO: see why the recovery sets were different + -- Original recovery expression failed: For a test case, the use of '=' in the recovery expression causes an error, because + --the input left is not matched as an statment and the repetition block* finishes + TypeReturnTypes <- ({} '' -> 'TypeReturnTypes') -> adderror TypeReturnTypesRec (P '') -> TypeInteger + --TypeReturnTypesRec <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / '^' / ']' / NAME / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / !.) eatTk)* + TypeReturnTypesRec <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / '^' / ']' / NAME / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / !.) eatTk)* + + --Err_039: Use ParamSemicolonRec (Err_029) + ColonRecordField <- ({} '' -> 'ColonRecordField') -> adderror ParamSemicolonRec + + --Err_040: + TypeRecordField <- ({} '' -> 'TypeRecordField') -> adderror TypeRecordFieldRec (P '') -> TypeInteger + TypeRecordFieldRec <- (!('end' / NAME / ';') eatTk)* + + --Err_041: + EndBlock <- ({} '' -> 'EndBlock') -> adderror EndBlockRec + EndBlockRec <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / NAME / ';' / '(') eatTk)* + + --Err_042: + ExpWhile <- ({} '' -> 'ExpWhile') -> adderror ExpWhileRec (P '' -> defaultInt2) -> number_exp + ExpWhileRec <- (!'do' eatTk)* + + --Err_043: use TypeFuncRec (Err_027) + DoWhile <- ({} '' -> 'DoWhile') -> adderror TypeFuncRec + + --Err_044: use EndBlockRec (Err_041) + EndWhile <- ({} '' -> 'EndWhile') -> adderror EndBlockRec + + --Err_045: use AssignVarRec (Err_011) + UntilRepeat <- ({} '' -> 'UntilRepeat') -> adderror AssignVarRec + + --Err_046: use EndBlockRec (Err_041) + ExpRepeat <- ({} '' -> 'ExpRepeat') -> adderror EndBlockRec (P '' -> defaultInt2) -> number_exp + + --Err_047: + ExpIf <- ({} '' -> 'ExpIf') -> adderror ExpIfRec (P '' -> defaultInt2) -> number_exp + ExpIfRec <- (!'then' eatTk)* + + --Err_048: + ThenIf <- ({} '' -> 'ThenIf') -> adderror ThenIfRec + ThenIfRec <- (!('while' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / NAME / ';' / '(') eatTk)* + + --Err_049: use EndBlockRec (Err_041) + EndIf <- ({} '' -> 'EndIf') -> adderror EndBlockRec + + --Err_050: use NameImportRec (Err_015) + DeclFor <- ({} '' -> 'DeclFor') -> adderror NameImportRec (P '' -> defaultDeclName (P '') -> TypeInteger) -> Decl + + --Err_051: use AssignVarRec (Err_011) + AssignFor <- ({} '' -> 'AssignFor') -> adderror AssignVarRec + + --Err_052: + Exp1For <- ({} '' -> 'Exp1For') -> adderror Exp1ForRec (P '' -> defaultInt2) -> number_exp + Exp1ForRec <- (!',' eatTk)* + + --Err_053: use AssignVarRec (Err_011) + CommaFor <- ({} '' -> 'CommaFor') -> adderror AssignVarRec + + --Err_054: + Exp2For <- ({} '' -> 'Exp2For') -> adderror Exp2ForRec (P '' -> defaultInt2) -> number_exp + Exp2ForRec <- (!('do' / ',') eatTk)* + + --Err_055: use ExpWhileRec (Err_042) + Exp3For <- ({} '' -> 'Exp3For') -> adderror ExpWhileRec (P '' -> defaultInt2) -> number_exp + + --Err_056: use TypeFuncRec (Err_027) + DoFor <- ({} '' -> 'DoFor') -> adderror TypeFuncRec + + --Err_057: uses EndBlockRec (Err_041) + EndFor <- ({} '' -> 'EndFor') -> adderror EndBlockRec + + --Err_058: use NameImportRec (Err_015) + DeclLocal <- ({} '' -> 'DeclLocal') -> adderror NameImportRec {| (P ('' -> defaultDeclName) (P '') -> TypeInteger) -> Decl |} + + --Err_059: use AssignVarRec (Err_011) + AssignLocal <- ({} '' -> 'AssignLocal') -> adderror AssignVarRec + + --Err_060: uses EndBlockRec (Err_041) + ExpLocal <- ({} '' -> 'ExpLocal') -> adderror EndBlockRec (P '' -> defaultInt2) -> number_exp + + --Err_XXX: the algorithm did not insert the label corresponding to AssignAssign in rule 'statement' + AssignAssign <- ({} '' -> 'AssignAssign') -> adderror AssignAssignRec + AssignAssignRec <- (!('~' / '{' / 'true' / 'not' / 'nil' / 'false' / NAME / NUMBER / '-' / '(' / '#' / STRINGLIT) eatTk)* + + --Err_XXX: the algorithm did not insert the two labels corresponding to ExpAssign in rule 'statement' + -- use EndBlockRec (Err_041) + ExpAssign <- ({} '' -> 'ExpAssign') -> adderror EndBlockRec {| (P '' -> defaultInt2) -> number_exp |} + + --Err_XXX: I renamed the label ExpAssign used in the predicate to ExpAssignPred, since its recovery rule is different + -- use EndBlockRec (Err_041) + ExpAssignPred <- ({} '' -> 'ExpAssignPred') -> adderror (exp ASSIGN) EndBlockRec + + --Err_XXX: the algorithm did not insert the label corresponding to ExpStat in rule 'statement' + -- uses EndBlockRec + ExpStat <- ({} '' -> 'ExpStat') -> adderror (exp) EndBlockRec + --ExpStatRec <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / NAME / ';' / '(') eatTk)* + + --Err_061: use ExpIfRec (Err_047) + ExpElseIf <- ({} '' -> 'ExpElseIf') -> adderror ExpIfRec (P '' -> defaultInt2) -> number_exp + + --Err_062: use ThenIfRec (Err_048) + ThenElseIf <- ({} '' -> 'ThenElseIf') -> adderror ThenIfRec + + -- Titan grammar use a unique label (OpExp) to expressions e2 (Err_063), e3 (Err_064), e4 (Err_065), e5 (Err_066), + -- e6 (Err_067), e7 (Err_068), e8 (Err_069, Err_070)), e10 (Err_071), e11 (Err_072, Err_073) + -- Use the recovery set of e11 in rule e12 (Err_073) + + --Err_73: OpExp (e11 in rule e12) + OpExp <- ({} '' -> 'OpExp') -> adderror OpExpRec (P '' -> defaultInt2) -> number_exp + OpExpRec <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / ']' / NAME / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / '//' / '/' / '..' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / !.) eatTk)* + + --Err_074: + NameColonExpSuf <- ({} '' -> 'NameColonExpSuf') -> adderror NameColonExpSufRec ('' -> defaultColonName) + NameColonExpSufRec <- (!('{' / '(' / STRINGLIT) eatTk)* + + --Err_075: + FuncArgsExpSuf <- ({} '' -> 'FuncArgsExpSuf') -> adderror FuncArgsExpSufRec {| (P '' -> defaultInt2) -> number_exp |} + FuncArgsExpSufRec <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / NAME / '>>' / '>=' / '>' / '==' / '=' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / !. / STRINGLIT) eatTk)* + + --Err_076 and Err_085: + ExpExpSuf <- ({} '' -> 'ExpExpSuf') -> adderror ExpExpSufRec (P '' -> defaultInt2) -> number_exp + ExpExpSufRec <- (!']' eatTk)* + + --Err_077: use FuncArgsExpSufRec (Err_075) + RBracketExpSuf <- ({} '' -> 'RBracketExpSuf') -> adderror FuncArgsExpSufRec + + --Err_078: use FuncArgsExpSufRec (Err_075) + NameDotExpSuf <- ({} '' -> 'NameDotExpSuf') -> adderror FuncArgsExpSufRec ('' -> defaultDotName) + + --Err_079: use StringLParImportRec (Err_018) + ExpSimpleExp <- ({} '' -> 'ExpSimpleExp') -> adderror StringLParImportRec (P '' -> defaultInt2) -> number_exp + + --Err_080: + RParSimpleExp <- ({} '' -> 'RParSimpleExp') -> adderror RParSimpleExpRec + RParSimpleExpRec <- (!('~=' / '~' / '}' / '|' / '{' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'as' / 'and' / '^' / ']' / '[' / NAME / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / ':' / '//' / '/' / '..' / '.' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / !. / STRINGLIT) eatTk)* + + --Err_XXX: the algorithm did not insert the label corresponding to CastMissingType in rule 'castexp' (using the FOLLOW of castexp in recovery rule) + CastMissingType <- ({} '' -> 'CastMissingType') -> adderror CastMissingTypeRec (P '' -> defaultInt2 (P '') -> TypeInteger) -> ExpCast + CastMissingTypeRec <- (!('~=' / '~' / '}' / '|' / 'while' / 'until' / 'then' / 'return' / 'repeat' / 'record' / 'or' / 'local' / 'if' / 'function' / 'for' / 'end' / 'elseif' / 'else' / 'do' / 'and' / '^' / ']' / NAME / '>>' / '>=' / '>' / '==' / '<=' / '<<' / '<' / ';' / '//' / '/' / '..' / '-' / ',' / '+' / '*' / ')' / '(' / '&' / '%%' / !.) eatTk)* + + --Err_081: use NameImportRec (Err_015) + ExpVarList <- ({} '' -> 'ExpVarList') -> adderror NameImportRec + + --Err_082: use FuncArgsExpSufRec (Err_075) + RParFuncArgs <- ({} '' -> 'RParFuncArgs') -> adderror FuncArgsExpSufRec + + --Err_083: + ExpExpList <- ({} '' -> 'ExpExpList') -> adderror ExpExpListRec (P '' -> defaultInt2) -> number_exp + ExpExpListRec <- (!('while' / 'until' / 'return' / 'repeat' / 'local' / 'if' / 'for' / 'end' / 'elseif' / 'else' / 'do' / NAME / ';' / ')' / '(') eatTk)* + + --Err_084: use FuncArgsExpSufRec (Err_075) + RCurlyInitList <- ({} '' -> 'RCurlyInitList') -> adderror FuncArgsExpSufRec + + --Err_XXX: the algorithm did not insert the label corresponding to ExpFieldList in rule 'fieldlist' + --use FuncArgsExpSufRec (Err_075) + ExpFieldList <- ({} '' -> 'ExpFieldList') -> adderror FuncArgsExpSufRec (P '' -> defaultInt2) -> number_exp + + --Err_085: the grammar uses ExpExpSuf (Err_076) again. Both uses of this label have the same recovery set + + --Err_086: the grammar used to use RBracketExpSuff, but this instance has very difference recovery set + --Created label RBracketExpKey: not in parser spec. Use NameImportRec (Err_015) + RBracketExpKey <- ({} '' -> 'RBracketExpKey') -> adderror NameImportRec + ]], defs) + +local totalErr = 0 +local nSynErr = 0 + function parser.parse(filename, input) -- Abort if someone calls this non-reentrant parser recursively assert(type(filename) == "string") assert(THIS_FILENAME == nil) THIS_FILENAME = filename + synerr = {} local ast, err, errpos = grammar:match(input) + --print("ast, err, errpos, synerr", ast, err, errpos, #synerr) THIS_FILENAME = nil - if ast then + if ast and #synerr == 0 then return ast else - local loc = location.from_pos(filename, input, errpos) + assert(ast, "Ouch! We did not get an ast for " .. tostring(err) ..'\n' .. input) + totalErr = totalErr + #synerr + nSynErr = nSynErr + 1 + --print("err = ", synerr[1].lab, " #synerr = ", #synerr, " total = ", totalErr, " nErr = ", nSynErr) + --if #synerr > 1 then + -- for i, v in ipairs(synerr) do + -- print(i, v.lab, syntax_errors.errors[v.lab]) + -- end + --end + local loc + if ast then + --print(parser.pretty_print_ast(ast)) + loc = synerr[1].pos + err = synerr[1].lab + --print("loc = ", loc, "err = ", err) + loc = location.from_pos(filename, input, loc) + else + loc = location.from_pos(filename, input, errpos) + end return false, { label = err, loc = loc } end end diff --git a/titan-compiler/recovery.txt b/titan-compiler/recovery.txt new file mode 100644 index 0000000..08ba979 --- /dev/null +++ b/titan-compiler/recovery.txt @@ -0,0 +1,46 @@ +* To do recovery properly, the grammar needs a rule to consume a token. This rule will + be used while trying to reach a synchronization token + +* The recovery pattern associated with label NameRecord (Err_007) will not work, because + it is the same pattern (NAME) that failed to match in the regular grammar. + Update: it worked. I think it did not work before because I have not annotated all the rules. + Nevertheless, the recovery expression does not seem good. + +* The original grammar uses the same set of labels (six in total) for 'import' and 'foreign' rules + +* The label DeclParList is used by rules 'declist' and 'paramlist', but each rule has a different + recovery expression associated with this labels. I am using two distinct labels: DeclList and ParamList + In 'first.lua', I need to check the computatation of FOLLOW in case of an expression p*. + It seems that ',' should be in the recovery expression of DeclParList. + +* The label TypeDecl is also used by two rules, 'param' and 'decl', but has different recovery expressions + in each rule. I will use TypeParam for 'param' and TypeDecl for 'decl'. + +* Check why the recovery did not work for label RParenTypelist. + +* In rule 'rettype', the algorithm did not insert the two labels corresponding to TypeReturnTypes. + I did not see a specific test for this label in 'parser_spec'. Label 'TypeReturnTypes' was thrown + by a test related to rule 'type'. + +* As rule 'rettype', rule 'type' also uses 'TypeReturnTypes'. The first occurrence of this label in rule 'type' + corresponds to label Err_033. I am using the recovery set of Err_033 for all occurrences of TypeReturnTypes, + since the recovery set of Err_033 is equal to the FOLLOW set of 'rettype'. + The second occurrence of 'TypeReturnTypes' in 'type' was not annotated by the algorithm. + The recovery fails in example "local x: (a, b) -> = nil = nil", because 'TypeReturnTypes' syncs + with the first '=' and the rest of the input '= nil' is not matched by the statement rule. + I removed '=' from the recovery expression and the recovery worked. + +* The recovery rule for DecLocal does not work for input 'local (xyz) = 42'. + It captures 'xyz', although '(xyz)' is not a valid name, and the recovery set has only '='. + I commented out this test in 'parser_spec'. + FIXED: The use of NAME in the recovery rule eatTk was producing captures + See also the use of NUMBER and STRINGLIT + +* In a similar way, the recovery rules for ExpAssign and ExpStat also do not work for + '(xzy) = 42' and '(f)', respectively, we get the error message 'too many captures' + FIXED: The error was caused because these labels are used in predicates to test whether + the input is invalid. Their recovery expression should then consume at least the part + of the input that was matched by the predicate + +* I used just one label OpExp, although each expression has a differente recovery set, because + LPeg 1.0.1 imposes a limit of 255 rules in a grammar. LPeg 1.0.0 does have this limit. diff --git a/titan-compiler/typedecl.lua b/titan-compiler/typedecl.lua index 8b01c3d..45d3796 100644 --- a/titan-compiler/typedecl.lua +++ b/titan-compiler/typedecl.lua @@ -9,7 +9,7 @@ return function(prefix, types) constructors[consname] = function(...) local args = table.pack(...) if args.n ~= #fields then - error("missing arguments for " .. consname) + error("missing arguments for " .. consname .. tostring(args.n) .. tostring(#fields)) end local node = { _tag = tag } for i, field in ipairs(fields) do