/* [The "BSD licence"] Copyright (c) 2017 Sasa Coh, Michał Błotniak Copyright (c) 2019 Ivan Kochurkin, kvanttt@gmail.com, Positive Technologies Copyright (c) 2019 Dmitry Rassadin, flipparassa@gmail.com,Positive Technologies All rights reserved. Copyright (c) 2021 Martin Mirchev, mirchevmartin2203@gmail.com Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * A Go grammar for ANTLR 4 derived from the Go Language Specification https://golang.org/ref/spec */ parser grammar GoParser; // import GoLexer; options { tokenVocab = GoLexer; language = Cpp; // superClass = GoParserBase; } sourceFile: packageClause eoss* (importDecl eoss*)* ( (functionDecl | methodDecl | declaration) eoss* )* EOF; packageClause: PACKAGE packageName = IDENTIFIER; importDecl: IMPORT (importSpec | L_PAREN (importSpec eoss)* R_PAREN); importSpec: alias = (DOT | IDENTIFIER)? importPath; importPath: string_; declaration: constDecl | typeDecl | varDecl; constDecl: CONST (constSpec | L_PAREN (constSpec eoss)* R_PAREN); constSpec: identifierList (type_? ASSIGN expressionList)?; identifierList: IDENTIFIER (COMMA IDENTIFIER)*; expressionList: expression (COMMA expression)*; typeDecl: TYPE (typeSpec | L_PAREN (typeSpec eoss)* R_PAREN); typeSpec: IDENTIFIER ASSIGN? type_; // Function declarations functionDecl: FUNC IDENTIFIER (signature block?); methodDecl: FUNC receiver IDENTIFIER ( signature block?); receiver: parameters; varDecl: VAR (varSpec | L_PAREN (varSpec eoss)* R_PAREN); varSpec: identifierList ( type_ (ASSIGN expressionList)? | ASSIGN expressionList ); block: L_CURLY eoss* statementList? R_CURLY; statementList: (statement eoss+)+; statement: declaration | labeledStmt | simpleStmt | goStmt | returnStmt | breakStmt | continueStmt | gotoStmt | fallthroughStmt | block | ifStmt | switchStmt | selectStmt | forStmt | deferStmt; simpleStmt: sendStmt | incDecStmt | assignment | expressionStmt | shortVarDecl; expressionStmt: expression; sendStmt: channel = expression RECEIVE expression; incDecStmt: expression (PLUS_PLUS | MINUS_MINUS); assignment: expressionList assign_op expressionList; assign_op: ( PLUS | MINUS | OR | CARET | STAR | DIV | MOD | LSHIFT | RSHIFT | AMPERSAND | BIT_CLEAR )? ASSIGN; shortVarDecl: identifierList DECLARE_ASSIGN expressionList; emptyStmt: EOSSS | SEMI; labeledStmt: IDENTIFIER COLON statement?; returnStmt: RETURN expressionList?; breakStmt: BREAK IDENTIFIER?; continueStmt: CONTINUE IDENTIFIER?; gotoStmt: GOTO IDENTIFIER; fallthroughStmt: FALLTHROUGH; deferStmt: DEFER expression; ifStmt: IF ( expression | eoss expression | simpleStmt eoss expression ) block ( ELSE (ifStmt | block) )?; switchStmt: exprSwitchStmt | typeSwitchStmt; exprSwitchStmt: SWITCH (expression? | simpleStmt? eoss expression? ) L_CURLY exprCaseClause* R_CURLY; exprCaseClause: exprSwitchCase COLON statementList?; exprSwitchCase: CASE expressionList | DEFAULT; typeSwitchStmt: SWITCH ( typeSwitchGuard | eoss typeSwitchGuard | simpleStmt eoss typeSwitchGuard) L_CURLY typeCaseClause* R_CURLY; typeSwitchGuard: (IDENTIFIER DECLARE_ASSIGN)? primaryExpr DOT L_PAREN TYPE R_PAREN; typeCaseClause: typeSwitchCase COLON statementList?; typeSwitchCase: CASE typeList | DEFAULT; typeList: (type_ | NIL_LIT) (COMMA (type_ | NIL_LIT))*; selectStmt: SELECT L_CURLY commClause* R_CURLY; commClause: commCase COLON statementList?; commCase: CASE (sendStmt | recvStmt) | DEFAULT; recvStmt: (expressionList ASSIGN | identifierList DECLARE_ASSIGN)? recvExpr = expression; forStmt: FOR (expression | forClause | rangeClause)? block; forClause: initStmt = simpleStmt? eoss expression? eoss postStmt = simpleStmt?; rangeClause: ( expressionList ASSIGN | identifierList DECLARE_ASSIGN )? RANGE expression; goStmt: GO expression; type_: typeName | typeLit | L_PAREN type_ R_PAREN; typeName: qualifiedIdent | IDENTIFIER; typeLit: arrayType | structType | pointerType | functionType | interfaceType | sliceType | mapType | channelType; arrayType: L_BRACKET arrayLength R_BRACKET elementType; arrayLength: expression; elementType: type_; pointerType: STAR type_; interfaceType: INTERFACE L_CURLY ((methodSpec | typeName) eoss)* R_CURLY; sliceType: L_BRACKET R_BRACKET elementType; // It's possible to replace `type` with more restricted typeLit list and also pay attention to nil maps mapType: MAP L_BRACKET type_ R_BRACKET elementType; channelType: (CHAN | CHAN RECEIVE | RECEIVE CHAN) elementType; methodSpec: IDENTIFIER parameters result | IDENTIFIER parameters; functionType: FUNC signature; signature: parameters result | parameters; result: parameters | type_; parameters: L_PAREN (parameterDecl (COMMA parameterDecl)* COMMA?)? R_PAREN; parameterDecl: identifierList? ELLIPSIS? type_; expression: primaryExpr #PrimaryExpression | unary_op = ( PLUS | MINUS | EXCLAMATION | CARET | STAR | AMPERSAND | RECEIVE ) expression # UnaryOperation | expression mul_op = ( STAR | DIV | MOD | LSHIFT | RSHIFT | AMPERSAND | BIT_CLEAR ) expression #MulDivOperation | expression add_op = (PLUS | MINUS | OR | CARET) expression #PlusMinusOperation | expression rel_op = ( EQUALS | NOT_EQUALS | LESS | LESS_OR_EQUALS | GREATER | GREATER_OR_EQUALS ) expression #RelationOperation | expression LOGICAL_AND expression #LogicalAndOperation | expression LOGICAL_OR expression #LogicalOrOperation ; primaryExpr: operand | conversion | methodExpr | primaryExpr ( (DOT IDENTIFIER) | index | slice_ | typeAssertion | arguments ); conversion: nonNamedType L_PAREN expression COMMA? R_PAREN; nonNamedType: typeLit | L_PAREN nonNamedType R_PAREN; operand: literal | operandName | L_PAREN expression R_PAREN; literal: basicLit | compositeLit | functionLit; basicLit: NIL_LIT | integer | string_ | FLOAT_LIT; integer: DECIMAL_LIT | BINARY_LIT | OCTAL_LIT | HEX_LIT | IMAGINARY_LIT | RUNE_LIT; operandName: IDENTIFIER; qualifiedIdent: IDENTIFIER DOT IDENTIFIER; compositeLit: literalType literalValue; literalType: structType | arrayType | L_BRACKET ELLIPSIS R_BRACKET elementType | sliceType | mapType | typeName; literalValue: L_CURLY (elementList COMMA?)? R_CURLY; elementList: keyedElement (COMMA keyedElement)*; keyedElement: (key COLON)? element; key: expression | literalValue; element: expression | literalValue; structType: STRUCT L_CURLY (fieldDecl eoss)* R_CURLY; fieldDecl: ( identifierList type_ | embeddedField ) tag = string_?; string_: RAW_STRING_LIT | INTERPRETED_STRING_LIT; embeddedField: STAR? typeName; functionLit: FUNC signature block; // function index: L_BRACKET expression R_BRACKET; slice_: L_BRACKET ( expression? COLON expression? | expression? COLON expression COLON expression ) R_BRACKET; typeAssertion: DOT L_PAREN type_ R_PAREN; arguments: L_PAREN ( (expressionList | nonNamedType (COMMA expressionList)?) ELLIPSIS? COMMA? )? R_PAREN; methodExpr: nonNamedType DOT IDENTIFIER; //receiverType: typeName | '(' ('*' typeName | receiverType) ')'; receiverType: type_; eoss: SEMI | EOSSS | HUANHANG | HUANHANGG // | {closingBracket()}? ;