Netbeans E-Lang language support
"Marcelo D. Ré" <[email protected]> Wed, 21 Aug 2013 12:53:25 -0300
| Newsgroups | gmane.comp.lang.e.general |
|---|---|
| Message-ID | <[email protected]> |
Hi All!
Some time ago, I was trying to write a plugin that support E in
Netbeans. The module work but had some bugs, and since the need of
develop in E postponed, I abandoned the project.
Now the need to develop in E has returned. Unfortunately the module
that I had used is no more supported in Netbeans, so I start again a new
project, this time directly in Antlr.
I get the easy part working (I think), the Lexer but have problem
with the Parser. I have rewrite the grammar in Antlr3 and I use
Antlrwork1.5 to generate the Lexer/Parser.
I do not know enough about Antlr son my ".g" file surely has bug.
Actually it generate a Parser of about 867kb and it wont compile.
Currently the module have syntax highlight but without the Parser I
could not get error detection. If anyone is interested I can upload the
module to sourceforge or github.
Are there somebody that could help me with this? I need to detect
what is the error that generate a big parser. I attach the ".g"
Thanks
Marcelo
_______________________________________________
e-lang mailing list
[email protected]
http://www.eros-os.org/mailman/listinfo/e-lang
e.g
(text/plain, 30.2 KB)
// Definición del lenguage basada en e.g, elex.g y quasi.g
grammar e;
options {
output=AST;
k = 2; // number of token lookahead
language=Java;
}
// definition of tokens
/*
TOKEN:keyword:(
"abstract" | "accum" | "an" | "as" | "assert" | "attribute" |
"be" | "begin" | "behalf" | "belief" | "believe" | "believes" | "bind" | "break" |
"case" | "catch" | "class" | "const" | "constructor" | "continue" |
"datatype" | "declare" | "def" | "default" | "define" | "defmacro" | "delegate" |
"delicate" | "deprecated" | "dispatch" | "do" |
"else" | "encapsulate" | "encapsulated" | "encapsulates" | "end" |
"ensure" | "enum" | "eventual" | "eventually" | "export" | "extends" | "escape" |
"exit" | "extends" |
"facet" | "finally" | "fn" | "for" | "forall" | "fun" | "function" |
"given" | "guards" | "hidden" | "hides" |
"if" | "implements" | "in" | "inline" | "into" | "interface" | "is" |
"know" | "knows" | "lambda" | "let" |
"match" | "meta" | "method" | "methods" | "module" |
"namespace" | "native" | "obeys" | "on" | "obeys" | "octet" | "oneway" | "operator" |
"package" | "pragma" | "private" | "println" | "protected" | "public" |
"raises" | "reliance" | "reliant" | "relies" | "rely" | "require" |
"return" | "r eveal" |
"sake" | "static" | "select" | "signed" | "static" | "struct" | "suchthat" |
"supports" | "suspect" | "suspects" | "switch" | "synchronized" |
"this" | "throws" | "thunk" | "to" | "transient" | "truncatable" | "try" | "typedef" |
"unsigned" | "unum" | "uses" | "using" | "utf8" | "utf16" | "var" | "via" |
"virtual" | "void" | "volatile" |
"when" | "while" | "wstring" | "_"
)
*/
tokens {
BIND='bind';
BREAK='break';
CATCH= 'catch';
CONTINUE= 'continue';
DEF= 'def';
ELSE='else';
ESCAPE='escape';
EXIT='exit';
EXTENDS='extends';
FINALLY='finally';
FN='fn';
FOR='for';
GUARDS='guards';
IF='if';
IMPLEMENTS='implements';
IN='in';
INTERFACE='interface';
MATCH='match';
META='meta';
METHOD='method';
PRAGMA='pragma';
RETURN='return';
SWITCH='switch';
TO='to';
TRY='try';
VAR='var';
VIA='via';
WHEN='when';
WHILE='while';
UNDERSCORE='_';
ABSTRACT='abstract';
AN='an';
AS='as';
ASSERT='assert';
ATTRIBUTE='attribute';
BE='be';
BEGIN='begin';
BEHALF='behalf';
BELIEF='belief';
BELIEVE='believe';
BELIEVES='believes';
CASE='case';
CLASS='class';
CONST='const';
CONSTRUCTOR='constructor';
DATATYPE='datatype';
DECLARE='declare';
DEFAULT='default';
DEFINE='define';
DEFMACRO='defmacro';
DELICATE='delicate';
DEPRECATED='deprecated';
DISPATCH='dispatch';
DO='do';
ENCAPSULATE='encapsulate';
ENCAPSULATED='encapsulated';
ENCAPSULATES='encapsulates';
END='end';
ENSURE='ensure';
ENUM='enum';
EVENTUAL='eventual';
EVENTUALLY='eventually';
EXPORT='export';
FACET='facet';
FORALL='forall';
FUN='fun';
FUNCTION='function';
GIVEN='given';
HIDDEN='hidden';
HIDES='hides';
INLINE='inline';
INTO='into';
KNOW='know';
KNOWS='knows';
LAMBDA='lambda';
LET='let';
METHODS='methods';
NAMESPACE='namespace';
NATIVE='native';
OBEYS='obeys';
OCTET='octet';
ONEWAY='oneway';
OPERATOR='operator';
PACKAGE='package';
PRIVATE='private';
PROTECTED='protected';
PUBLIC='public';
RAISES='raises';
RELIANCE='reliance';
RELIANT='reliant';
RELIES='relies';
RELY='rely';
REVEAL='reveal';
SAKE='sake';
SIGNED='signed';
STATIC='static';
STRUCT='struct';
SUCHTHAT='suchthat';
SUPPORTS='supports';
SUSPECT='suspect';
SUSPECTS='suspects';
SYNCHRONIZED='synchronized';
THIS='this';
TRANSIENT='transient';
TRUNCATABLE='truncatable';
TYPEDEF='typedef';
UNSIGNED='unsigned';
UNUM='unum';
USES='uses';
USING='using';
UTF8='utf8';
UTF16='utf16';
VIRTUAL='virtual';
VOLATILE='volatile';
WSTRING='wstring';
OpLAnd='&&';
OpLOr='||';
OpSame='==';
OpNSame='!=';
OpButNot='&!';
OpLeq='<=';
OpABA='<=>';
OpGeq='>=';
OpThru='..';
OpTill='..!';
OpAsl='<<';
OpAsr='>>';
OpFlrDiv='//';
OpMod='%%';
OpPow='**';
OpAss=':=';
OpAssAdd='+=';
OpAssAnd='&=';
OpAssAprxDiv='/=';
OpAssFlrDiv='//=';
OpAssAsl='<<=';
OpAssAsr='>>=';
OpAssRemdr='%=';
OpAssMod='%%=';
OpAssMul='*=';
OpAssOr='|=';
OpAssPow='**=';
OpAssSub='-=';
OpAssXor='^=';
//OTHER funky tokens
Send='<-';
OpWhen='->';
MapsTo='=>';
MatchBind='=~';
MisMatch='!~';
OpScope='::';
DollarOpen='${'; //#/* "${" */
AtOpen='@{'; //#/* "@{" */
FLOAT64;
HEX;
}
WS: (' '|'\t')+ { $channel=HIDDEN; };
//#I don't know if this is right
EOL: '\r'('\n')*
|'\n' { $channel=HIDDEN; };
//#TOKEN:LiteralString:( '"' [^ '"']* '"' ) #/* Double quoted */
//#TOKEN:LiteralTwine:( '`' [^ '`']* '`' ) #/* Double quoted */
IDENT: (('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ); //#/* like Java's ident, but no "$"s, and not keyword */
//#TOKEN:VerbAssign:('=') #/* ID "=" */
/*
//"<" protocol ":" body ">"
URI:('<' (^ '-') (^ ('<'|'>'|':'))+ ('>' | ':' (^ ('>'|':'))+ '>'));
URI:('<' (('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*)
( '>' |
(':'
('a'..'z'|'A'..'Z'|'_'|'0'..'9'|
';'|'/'|'?'|':'|'@'|'&'|'='|'+'|'$'|','|'-'|
'.'|'!'|'~'|'*'|'\''|'('|')'|'%'|'\\'|'|'|'#'
)+
) '>'
)
)
TOKEN:URI:(('a'-'z'|'A'-'Z'|'_'|'0'-'9'|
';'|'/'|'?'|':'|'@'|'&'|'='|'+'|'$'|','|'-'|
'.'|'!'|'~'|'*'|'\''|'('|')'|'%'|'\\'|'|'|'#')+
)
*/
//--------- sacado de elex.g
fragment
URIBody: ( 'a'..'z'|'A'..'Z'|'_'|'0'..'9'
|';'|'/'|'?'|':'|'@'|'&'|'='|'+'|'$'|','|'-'
|'.'|'!'|'~'|'*'|'\''|'('|')'|'%'|'\\'|'|'|'#' )+
;
URI: ('<' IDENT ('>' | ':')) =>
'<' IDENT ( '>' //{$setType(URIGetter);}
| ':' ( (ANYWS)=> (LINESEP)* //{$setType(URIStart);}
| URIBody '>' )) //{$setType(URI);}
| '<' (LINESEP)* ;
//protected
ANYWS: ' '|'\t'|'\f'|'\r'|'\n' ;
//--------------------------
//#TOKEN:OpLt:('<')
//#TOKEN:OpGt:('>')
//#dollarIdent=('$' <IDENT>); #/* "$" ID */
//#atIdent=('@' (<IDENT>|'_')); #/* ("@" ID) | "@_" */
//DollarOpen:('${') #/* "${" */
//AtOpen:('@{') #/* "@{" */
//DocComment:
// ('/**' - '*/') { $channel=HIDDEN; };
DOC_COMMENT
: '/**'
//( // '\r' '\n' can be matched in one alternative or by matching
// '\r' in one iteration and '\n' in another. I am trying to
// handle any flavor of newline that comes in, but the language
// that allows both "\r\n" and "\r" and "\n" to all be valid
// newline is ambiguous. Consequently, the resulting grammar
// must be ambiguous. I'm shutting this warning off.
//{ LA(2)!='/' }? '*'
// | EOL
// | ~('*'|'\n'|'\r')
//)*
.*
'*/'
//BR
//{$setText("**comment hidden**");}
{$channel=HIDDEN;}
;
//comment:( '/*' - '*/' ) { $channel=HIDDEN; };
Line_comment: '#' (~('\n'|'\r'))* {$channel=HIDDEN;} ;
//#TOKEN:LiteralChar:(.?) #/* Unicode */
//Operator:( '(' | ')' | '[' | ']' | '{' | '}' | '.' | ':' | ';' | '+' | '-' |
// '<' | '>' | '!' | '~' | '?' | ',' | '|' | '_' | '=' | '$' | '@' |
// '*' | '/' );
//#'<' | '>' |
//#####################
//# Syntax definition #
//#####################
/*
# Comments and whitespaces should be ignored
SKIP:comment
SKIP:line_comment
SKIP:linesep
SKIP:EOL
SKIP:whitespace
#SKIP:LiteralChar
*/
//########################################################
//# symbol definitions - from elex.g
// hexadecimal digit
fragment
HEX_DIGIT : ('0'..'9'|'A'..'F'|'a'..'f') ;
fragment
OCTAL : ('0' ('0'..'9')) => ('0'..'7')+ ; // { $setType(OCTAL); };
// an integer
fragment
POSINT: ('0'..'9') ('0'..'9')* ;
fragment
FLOAT64 : POSINT ('.' POSINT | ('e' | 'E') EXPONENT) ;
fragment
EXPONENT: ('+'|'-')? POSINT ;
//// a numeric literal
//int: ('0x') => '0x' (HEX_DIGIT)+ //{ $setType(HEX); }
// | OCTAL
// | (FLOAT64) => FLOAT64 //{ $setType(FLOAT64); }
// | POSINT
// ;
/*
#TOKEN:INT_1:('0'-'7')
#octal='0' (<INT_1>)+;
#// an integer
#TOKEN:POSINT:(('0'-'9') ('0'-'9'|'_')*)
#float64 = <POSINT> ('.' <POSINT> | ('e' | 'E') exponent) ;
#exponent= ['+'|'-'] <POSINT> ;
*/
/*
#######################################################
#TOKEN:NotCharLiterals:([^ '\'' '\n' '\r' '\\'])
#char_literal = '\'' ( esc | <NotCharLiterals> ) '\''
#FIXME: deben agregarse los caracteres que deben ingnorarse
*/
CHAR_LITERAL : '\'' ( ESC | ~('\''|'\n'|'\r'|'\\') ) '\'' ;
//
LINESEP: (EOL)+ { $channel=HIDDEN; };
//
////#// string literals
LiteralString: '"' ( ESC
| EOL
| ~('"'|'\\'|'\n'|'\r')
)* '"' ;
//
fragment
ESC: '\\'
( 'n'
| 'r'
| 't'
| 'b'
| 'f'
| '"'
| '\''
| '@'
| '$'
| '`'
| '\\'
| ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
| '0'..'3'
('0'..'7'
('0'..'7')?
)?
| '4'..'7'
('0'..'7')?
)
;
//########################################################
////########## Datos obtenidos del archivo quasi.g
////#TOKEN:QuasiOpen:('`' [^ '`']*):<IN_QUASISTRING> #/* ("`" char*) | (char*), up to hole */
//
//QUASIBODY: '${' //{$setType(DOLLARCURLY); selector.push("e");}
// | '$' IDENTQ // {$setType(DOLLARHOLE);}
// | '@{' //{$setType(ATCURLY); selector.push("e");}
// | '@' IDENTQ //{$setType(ATHOLE);}
// | '$$' QUASIn
// | '$\\' QUASIn
// | '@@' QUASIn
// | '@\\' QUASIn
// | QUASI1 QUASIn
// | ('``')=> '``' QUASIn //lookahead is needed to not conflict
// | '`' //{$setType(QUASICLOSE);} {selector.pop();}
// ;
//QUASIBODY: ('${'|'@{') //{$setType(DOLLARCURLY); selector.push("e");}
// | ('$'|'@') IDENT // {$setType(DOLLARHOLE);}
// | QUASIn QUASIn
// | ('``')=> '``' QUASIn //lookahead is needed to not conflict
// | '`' //{$setType(QUASICLOSE);} {selector.pop();}
// ;
fragment
QUASIBODY: ~('"'|'\\'|'\n'|'\r');
fragment
QUASIn: ( QUASI1 | '$$' | '$\\' | '@@' | '@\\' | ('``') => '``')* ;
/*
QUASI1: ~('`'|'$'|'@'|'\r'|'\n')
| (options {generateAmbigWarnings=false;} :
'\r\n' | '\r' | '\n') {newline();}
;
*/
fragment
QUASI1: ~('`'|'$'|'@'|'\r'|'\n')
| ('\r\n' | '\r' | '\n')
;
//fragment
//IDENTQ: ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')* ;
////# -----------------------------------------------------------------------------------------
reserverd:(
'abstract' | 'an' | 'as' | 'assert' | 'attribute'
| 'be' | 'begin' | 'behalf' | 'belief' | 'believe' | 'believes'
| 'case' | 'class' | 'const' | 'constructor'
| 'datatype' | 'declare' | 'default' | 'define' | 'defmacro'
| 'delicate' | 'deprecated' | 'dispatch' | 'do'
| 'encapsulate' | 'encapsulated' | 'encapsulates'
| 'end' | 'ensure' | 'enum' | 'eventual' | 'eventually'
| 'export' | 'facet' | 'forall' | 'fun' | 'function'
| 'given' | 'hidden' | 'hides' | 'inline' | 'into'
| 'know' | 'knows' | 'lambda' | 'let' | 'methods'
| 'namespace' | 'native'
| 'obeys' | 'octet' | 'oneway' | 'operator'
| 'package' | 'private' | 'protected' | 'public'
| 'raises' | 'reliance' | 'reliant' | 'relies' | 'rely' | 'reveal'
| 'sake' | 'signed' | 'static' | 'struct'
| 'suchthat' | 'supports' | 'suspect' | 'suspects' | 'synchronized'
| 'this' | 'transient' | 'truncatable' | 'typedef'
| 'unsigned' | 'unum' | 'uses' | 'using' | 'utf8' | 'utf16'
| 'virtual' | 'volatile' | 'wstring'
);
sepword :
'catch' | 'else' | 'escape' | 'finally' | 'guards'
| 'thunk' | 'fn' | 'try' | IDENT | reserverd
| '->'
;
///*
//#Multi-Character Operators
//#TOKEN:operator:( '{' | '}' | '(' | ')' | ';' | ':=' | '||' | '&&' | '==' |
//# '!=' | '|' | '|=' | '^' | '^=' | '=~' | '!~' | '&' | '&=' |
//# '<' | '<=' | '>' | '>=' | '..' | '..!' | '<<' | '<<=' |
//# '>>' | '>>=' | '+' | '+=' | '-' | '-=' | '*' | '*=' |
//# '/' | '/=' | '//' | '//=' | '%' | '%=' | '%%' | '%%=' |
//# '**' | '**=' | '!' | '~' | '->' | '=>' | '::' | ':' |
//# '[' | ']' | '?' | ',' | '_' | '.' | '`' )
//*/
//# definition of grammar
//S : start;
start:
// pragma (';')* | seq;
(pragma (';' | LINESEP) | LINESEP)* seq;
// #pragma (';'|linesep)* | (seq)*;
pragma:
'pragma' '.' message;
metaExpr:
'meta' '.' message;
/*
br:
(linesep)*;
*/
/*
seq=
(linesep)* eExpr (((';' | linesep) (eExpr)?)+
)?;
seq:
eExpr (((";"! | LINESEP!) (eExpr)?)+ {##=#([SeqExpr],##);}
)?;
*/
seq:
// eExpr (';' eExpr)*
(eExpr ((';'|LINESEP) (eExpr)?)+)?
;
eExpr:
assign | ejector ;
//# defExpr | interfaceExpr | lambdaExpr | assign | ejector ;
basic:
ifExpr | forExpr | whileExpr | switchExpr | tryExpr
| escapeExpr | whenExpr | metaExpr | accumExpr;
ifExpr:
'if' parenExpr body ('else' (ifExpr | body))?
;
forExpr:
'for' forPatt 'in' assign body (catcher)?
//'for' forPatt 'in' br assign body (catcher)?
;
// the first pattern is actually the optional one. If it is missing, include an
// empty ignore pattern for it.
forPatt:
pattern ('=>' pattern)?
;
accumExpr:
'accum' call accumulator
;
accumulator:
'for' forPatt 'in' logical accumBody
| 'if' parenExpr accumBody
| 'while' parenExpr accumBody;
accumBody:
'{' ( '_' ( ('+' | '*' | '&' | '|') assign
| '.' verb parenArgs)
| accumulator
) '}'
//) br '}'
;
whenExpr:
'when' parenArgs '->' whenFn (catcher)* ('finally' body)?
;
whenFn:
objName params (':' guard)? body
;
whileExpr:
'while' parenExpr body (catcher)?
;
escapeExpr:
'escape' pattern body (catcher)?
;
lambdaExpr:
'thunk' body
| 'fn' paramList body
;
switchExpr:
'switch' parenExpr '{' (matcher)* '}'
//'switch' parenExpr '{' (matcher br)* '}'
;
tryExpr:
'try' body (catcher)* ('finally' body)?
;
bindNamer:
'bind' noun (':' guard)?
;
varNamer:
'var' nounExpr (':' guard)?
;
slotNamer:
'&' nounExpr (':' guard)?
;
// should forward declaration allow types?
docoDef:
doco (defExpr | interfaceExpr | lambdaExpr)
//[br] doco [br] (defExpr | interfaceExpr | lambdaExpr)
;
/*
defExpr:
'def'^ ( (objectPredict) => objName objectExpr
{##.setType(ObjectExpr);}
| (pattern ':=') => pattern ':='! rValue
{##.setType(IntoExpr);}
| bindName //forward declaration
{##.setType(IntoExpr);}
)
| 'bind'! bindExpr
| 'var'! bindExpr;
*/
/*
defExpr
'bind' bindExpr
| 'var' bindExpr
| 'def' (
objName_ objectExpr
| pattern ':=' rValue
| bindName_ (':' guard | objectExpr)?
)
;
defExpr:
'bind' bindExpr
| 'var' bindExpr
| 'def' (
objName objectExpr
| pattern (':=' rValue)?
)
;
*/
defExpr:
'def'^ ( (objectPredict) => objName objectExpr
//{##.setType(ObjectExpr);}
| (pattern ':=') => pattern ':=' rValue
//{##.setType(IntoExpr);}
| bindName //forward declaration
//{##.setType(IntoExpr);}
)
| 'bind' bindExpr
| 'var' bindExpr
;
rValue:
('(' eExpr (LINESEP)* ',') => '(' eExpr (LINESEP)* ',' eExpr (LINESEP)* ')'
// Can we support trinary-define with less lookahead?
| assign;
/* nbs
rValue:
'(' eExpr (',' eExpr)* ')'
| assign
;
// #('(' eExpr br ',') '(' eExpr br ',' eExpr br ')'
*/
bindExpr:
bindName
( ':=' assign
| objectExpr
);
// minimize the look-ahead for objectExpr
objectPredict:
objName ('extends' | 'implements' | '{'| '(' );
/*
objectExpr:
//(':'! guard)?
( ('extends' br order)?
('implements' br order (',' order)*)?
// trailing comma would be ambiguous with HideExpr
script
| params resultGuard body // function
);
*/
objectExpr:
( ('extends' order)?
('implements' order (',' order)*)?
script
| params resultGuard body
);
/* / The name pattern, or literal name, for an object definition
/# Para eliminar el problema de selección en defExpr es necesario redefinir
bindName y objName dado que si estan en la mima regla no se puede determinar
correctamente si se está invocando a uno u otra dado que comparte elementos.
*/
bindName_:
( nounExpr
| '&' nounExpr
| LiteralString
)
;
bindName: bindName_ (':' guard)?
;
objName_:
'_'
| 'bind' noun
| 'var' nounExpr
;
objName: bindName_ | objName_
;
script:
'{' (method)* (matcher)* '}'
// #'{' (method br)* (matcher br)* '}'
;
method:
doco ( 'to' methHead body
| 'method' methHead body
| 'on' methHead body
)
;
methHead:
params resultGuard
| verb params resultGuard;
matcher:
'match' pattern body
;
params:
'(' paramList ')'
;
paramList:
((key)? '=>') mapPattList
| (pattern (',' paramList)?)?
;
patternList:
(pattern (',' patternList)? )?
;
resultGuard:
(':' guard)? ('throws' guardList)?
;
//#requires at least one guard. cannot end with comma
guardList:
guard (',' guard)*
;
interfaceExpr:
'interface' objName
( ('guards' pattern)?
('extends' order (',' order)*)?
('implements' order (',' order)*)?
'{' (imethod)* '}'
| mtypes (':' guard)?
)
;
/*
interfaceExpr=
'interface' objName
( ('guards' br pattern)?
('extends' br order (',' order)*)?
('implements' br order (',' order)*)?
'{' (imethod br)* '}'
| mtypes (':' guard)?
)
;
*/
imethod:
doco ( 'to' imethHead
| 'method' imethHead
| 'on' imethHead
)
;
ptype:
nounExpr (':' guard)?
| '_' (':' guard)?
;
typeList:
(ptype (',' typeList)? )?
;
mtypes:
'(' typeList ')'
;
/*
mtypes=
'(' typeList br ')'
;
*/
imethHead:
mtypes resultGuard
| verb mtypes resultGuard;
// The current E grammar only let's you put these in a few places.
doco:
(DOC_COMMENT)?
;
/*
doco=
DocComment br
;
*/
body:
'{' seq '}'
;
/*
# Sacado de e.g
#// rules for expressions follow the pattern:
#// thisLevelExpression : nextHigherPrecedenceExpression
#// (OPERATOR nextHigherPrecedenceExpression)*
#// which is a standard recursive definition for a parsing an expression.
#// The legal assignment syntax are:
#// x := ...
#// x op= ... converts to x."op"(...)
#// x verb= ... converts to x.verb(...)
#// x[i...] := ... converts to x.put(i..., ...)
#// x::name := ... converts to x.setName(...)
#// x(i...) := ... converts to x.setRun(i..., ...)
#// Based on the above patterns, only nounExpr, nounExpr
#assign=
# cond ( ':=' assign
# | assignOp assign
# | verb '=' (('(') parenArgs | assign)
# )?
# | docoDef
# ;
#/
*/
assign: cond ( ':=' assign
| assignOp assign
)?
| docoDef
;
//| (verb '=') (parenArgs | assign)
assignOp:
'//=' | '+=' | '-=' | '*=' | '/='
| '%=' | '%%=' | '**=' | '>>=' | '<<=' | '&='
| '^=' | '|=';
ejector:
( 'break'
| 'continue'
| 'return'
) (('(' ')') => '(' ')' | assign | )
| '^' assign
;
// || is don't-care associative
cond:
condAnd ('||' condAnd
)*;
// && is don't-care associative
condAnd:
logical ('&&' logical
)*;
/*
#// ==, !=, &, |, ^, =~, and !~ are all non associative with each
#// other. & and |, normally used for associative operations, are each
#// made associative with themselves. None of the others even associate
#// with themselves. Perhaps ^ should?
*/
logical:
order ( ( '==' order
| '!=' order
| '&!' order
| '=~' pattern
| '!~' pattern
)
| ( '^' order)+
| ( '&' order)+
| ( '|' order)+
)?
;
order:
interval (( compareOp interval
| ':' guard
))?
;
// The br for ">" is because it is used to close URIs, where it cannot have a
// br.
compareOp:
'<' | '<=' | '<=>' | '>=' | '>'
;
/*
compareOp=
'<' | '<=' | '<=>' | '>=' | '>' br
;
*/
// .. and ..! are both non-associative (no plural form)
interval:
shift ( ('..' | '..!') shift)?
;
// << and >> are left-associative (no plural form)
shift:
add ( ('<<' | '>>') add)*
;
//+ and - are left associative
add:
mult (('+' | '-') mult)*
;
// *, /, //, %, and %% are left associative
mult:
pow (('*' | '/' | '//' | '%' | '%%') pow)*
;
// ** is non-associative
pow:
prefix ('**' prefix)?
;
// Unary prefix !, ~, &, *, and - are non-associative.
// Unary prefix !, ~, &, and * bind less tightly than unary postfix.
// Unary prefix -, because it will often be mistaken for part of a literal
// number rather than an operator, is not combinable with unary postfix, in
// order to avoid the following surprise:
// -3.pow(2) ==> -9
// If -3 were a literal, the answer would be 9. So, in E, you must say either
// (-3).pow(2) or -(3.pow(2))
// to disambiguate which you mean.
prefix:
postfix
| prefixOp postfix
| '-' prim
;
prefixOp:
('!' | '~' | '&' | '*' | '+')
;
// Calls and sends are left associative.
postfix:
call
;
// TODO deal with properties
call:
prim ( parenArgs
| '.' message
| '[' argList ']'
| '<-' ( parenArgs
| message
| '::' ('&')? prop
)
| '::' ('&')? prop
)*
;
//message:
// v:verb ( ("(") => parenArgs
// | /*curry*/ {#v.setType(CurryExpr);}
// );
/*
#message=
# verb ( ('(') parenArgs
# |
# );
*/
/* NBS
message:
verb (parenArgs)?
;
*/
message:
verb ( ('(') => parenArgs
| /*curry*/ // {##.setType(CurryExpr);}
);
parenArgs:
'(' argList ')';
lambdaArgs:
'(' argList ')' (sepword body)?
;
exprList:
(eExpr (',' eExpr)*)?
;
/*
exprList:
(eExpr br (',' exprList)?)?
;
*/
/*
argList:
[
eExpr ["," argList|"=>" mapList]
| '=>' mapList
]
;
*/
/* NBS
argList: (eExpr (',' eExpr |
'=>' eExpr (',' argList)?
)*
)?
;
*/
argList:
((eExpr)? '=>') => mapList // {warn("map-tail");}
| (eExpr (LINESEP)* (',' argList)?)?
;
/*
argList:
((eExpr)? '=>') mapList
| (eExpr br (',' argList)?)?
;
prim:
literal
| basic
| nounExpr (quasiString)?
| parenExpr (quasiString)?
| quasiString
| URI
| '[' argList ']'
| body
;
*/
prim:
literal
| basic
| nounExpr (quasiString //{##=#([QuasiLiteralExpr],##);}
)?
| parenExpr (quasiString //{##=#([QuasiLiteralExpr],##);
// warn("***We may deprecate this***");}
)?
| quasiString // {##=#([QuasiLiteralExpr,
// "simple"],
// [STRING,"simple"],##);}
// | URI {##=#([URIExpr],##);}
| '['^ ( ((eExpr)? '=>') => mapList // {##.setType(MapExpr);}
| exprList // {##.setType(TupleExpr);}
) ']'
| body // {##=#([HideExpr],##);}
;
/*
| '[' ( [eExpr] '=>' mapList
| exprList
) ']'
*/
mapList:
(map (',' map)*)?
;
/*
mapList:
(map br (',' mapList)?)?
;
*/
map:
eExpr '=>' eExpr
| '=>' ( nounExpr
| '&' nounExpr
| 'def' nounExpr
)
;
//Property names for use e.g., with the :: syntax.
// Should the "&" handling be here?
prop:
IDENT | LiteralString;
// a method selector
verb:
IDENT | LiteralString;
//// a numeric literal
integer: ('0x') => '0x' (HEX_DIGIT)+ //{ $setType(HEX); }
| OCTAL
| (FLOAT64) => FLOAT64 //{ $setType(FLOAT64); }
| POSINT
;
//literal:
// (int | HEXNUM | OCTALNUM | LiteralString | CHAR_LITERAL );
literal:
LiteralString | CHAR_LITERAL | integer;
//#(int | float64 | hex | octal | <LiteralString> | <char_literal> );
//# int contiene a | <LiteralFloat64>
noun:
IDENT
| uriGetter
| '::' (LiteralString | IDENT);
//#### revisar acá la definición de urigetter sacada de elex.g
//#uriGetter= '<' <IDENT> [':' [(<URI>|<IDENT>)+]] '>';
uriGetter: URI;
/*
uriGetter: ('<' IDENT ('>' | ':'))
'<' IDENT ( '>'
| ':' ( (ANYWS) br
| URI '>'))
| '<' br
;
*/
// A guard is a nounExpr, a URI, a parenExpr, or a guard followed by [argList].
guard:
(nounExpr | parenExpr) ('[' argList ']')*
;
catcher:
'catch' pattern body
;
// Patterns
pattern:
subPattern ('?' parenExpr)?
;
subPattern:
nounExpr ( ':' guard
| quasiString
)?
| '_' (':' guard)?
| ':' guard
| bindNamer
| varNamer
| slotNamer
| quasiString
| '==' prim
| '!=' prim
| compareOp prim
| ('[' (key)? '=>') '[' mapPattList ']' ('|' subPattern)?
| '[' patternList ']' ( (':' guard)?
| ('+' subPattern)
)
;
/*
subPattern=
nounExpr ( (':' guard)?
| quasiString
)
| '_' (':' guard)?
| ':' guard
| bindNamer
| varNamer
| slotNamer
| quasiString
| '==' prim
| '!=' prim
| compareOp prim
| ('[' (key)? '=>') '[' mapPattList br ']' ('|' subPattern)?
| '[' patternList br ']' ( (':' guard)?
| ('+' subPattern)
)
;
*/
// namePatts are patterns that bind exactly one name.
// this is expanded inline into eqPatt, but used directly elsewhere
namePatt:
nounExpr (':' guard)?
| bindNamer
| varNamer
| slotNamer
;
nounExpr:
noun
| dollarHole
| atHole
;
dollarHole:'$' ('{' POSINT '}'|POSINT|'$');
/*
dollarHole:
'${' LiteralInteger '}'
| '$' LiteralInteger
| '$$'
#'$' ('{' <LiteralInteger> '}'|<LiteralInteger>|'$')
;
*/
//'$' ('{' <POSINT> '}'|<POSINT>|'$')
atHole:
'@{' POSINT '}'
| '@' POSINT
;
// #'@' ('{' <LiteralInteger> '}'|<LiteralInteger>);
// #'@' ('{' <POSINT> '}'|<POSINT>);
key:
parenExpr | literal;
parenExpr:
'(' seq ')';
mapPattList:
(mapPattern (',' mapPattList)? )?;
mapPattern:
key '=>' pattern (':=' order)?
| '=>' namePatt (':=' order)?;
// QUASI support
/*
quasiString:
QUASIOPEN! ( exprHole
| pattHole
| QUASIBODY
| DOLLARHOLE
| ATHOLE
)* {##=#([QuasiContent],##);}
QUASICLOSE!; // NOTE: '`' is the QUASICLOSE token in the quasi lexer
*/
quasiString:
'`' ( exprHole
| pattHole
| QUASIBODY
| dollarHole
| atHole
)* // {##=#([QuasiContent],##);}
'`'; // NOTE: '`' is the QUASICLOSE token in the quasi lexer
/*
exprHole:
DOLLARCURLY^ br eExpr br {##.setType(DOLLARHOLE);}
'}'!;
*/
exprHole:
DollarOpen^ (LINESEP)* eExpr (LINESEP)* // {##.setType(DOLLARHOLE);}
'}';
/*
pattHole:
ATCURLY! br pattern br {##.setType(ATHOLE);}
'}'!;
*/
pattHole:
AtOpen (LINESEP)* pattern (LINESEP)* // {##.setType(ATHOLE);}
'}';