ometa Scanner { real_semicolon = spaces ';', magic_semicolon = &((~newline space)* (newline | end | ')' | '}')), token ';' = real_semicolon | magic_semicolon, token `name = spaces &('_'* upper) identifier:x -> [`parsing_name, x], token `name = spaces &('_'* lower) identifier:x -> [`scanning_name, x], token `token = spaces str('"', '"'):x -> [`token, x] | spaces str('`', '`'):x -> [`token, x], token :t = spaces seq(t) -> [t, t], production_name = token(`name), _token = token(`token), newline = '\n', /* the Unicode code point U+000A */ unicode_char = ~newline char, /* an arbitrary Unicode code point except newline */ unicode_letter = ^letter, /* a Unicode code point classified as "Letter" */ unicode_digit = ^digit, /* a Unicode code point classified as "Decimal Digit" */ decimal_digit = charRange("0", "9"), octal_digit = charRange("0", "7"), hex_digit = charRange("0", "9") | charRange("A", "F") | charRange("a", "f"), letter = unicode_letter | "_", identifier = , charRange :from :to = char:x ?(from <= x && x <= to) -> x, str :from :to = seq(from) <(~seq(to) char)*>:x seq(to) -> x, scan :name = spaces apply(name) } ometa EBNFParser <: Scanner { Grammar = Production+:xs -> [`Grammar].concat(xs), Production = spaces :line -> [`Production, name, expr, line], Expression = Alternative:x ("|" Alternative)*:xs -> [`Expression, x].concat(xs), Alternative = Term+:xs -> [`Alternative].concat(xs), Term = (production_name | Range | _token | Group | Option | Repetition):x -> [`Term, x], Range = _token:x "…" _token:y -> [`Range, x, y], Group = "(" Expression:x ")" -> [`Group, x], Option = "[" Expression:x "]" -> [`Option, x], Repetition = "{" Expression:x "}" -> [`Repetition, x] } ometa EBNFTranslator { trans [parsing_name:t apply(t):ans] -> ans, trans [scanning_name:t apply(['_',t].join('')):ans] -> ans, expected :t [exactly(t) apply(t):ans] -> ans, singleton :t [exactly(t) term:ans] -> ans, scanning ?(this.is_scanning), parsing ?(!this.is_scanning), _scanning_name :name scanning -> name, _scanning_name :name parsing -> ['scan(', name.toProgramString(), ')'].join(''), _parsing_name :name parsing -> name, parsing_name = [&('_'* upper) anything+], scanning_name = [&('_'* lower) anything+], quote scanning -> '\'', quote parsing -> '"', _token [char*:s] quote:q -> [q, s.map(escapeChar).join(''), q].join(''), eol = (~'\n' space)* ('\n' | end), comment_line = ~end (~eol char)*:xs eol -> ['// ', xs.join('')].join(''), comment_lines = [eol? comment_line*:xs] -> xs.join('\n'), exp = undefined->'empty' | expected(`Expression) | alt, alt = expected(`Alternative) | term, term = str_alt | expected(`Term) | sing, sing = singleton(`Alternative) | singleton(`Expression) | prim, prim = [[&lower anything+]:t :prim] -> prim | paren, paren trans:x -> ['(', x, ')'].join(''), production_name [`scanning_name :name] -> {this.is_scanning=true; name}, production_name [`parsing_name :name] -> {this.is_scanning=false; name}, tok_term [`Term [`token _token:x]] -> x, rep_term [`Term [`Repetition alt:expression]] -> expression, str_alt scanning rep_term:x &tok_term:to -> ['(', '~', to, ' ', x, ')', '*'].join(''), Grammar expected(`Production)*:rules -> ['ometa Parser <: Scanner {\n', rules.join(',\n'), '\n}\n'].join(''), Production production_name:name exp:exp comment_lines:lines -> [lines, '\n ', name, ' = ', exp].join(''), Expression alt+:alts -> alts.join(' | '), Alternative term+:terms -> terms.join(' '), Term trans:term -> term, Range trans:from trans:to -> ['charRange', '(', from, ', ', to, ')'].join(''), Group trans:expression -> ['(', expression, ')'].join(''), Option term:expression -> [expression, '?'].join(''), Repetition term:expression -> [expression, '*'].join('') } EBNFTranslator.initialize = function() { this.is_scanning = false } grammar = """ Grammar = Production { Production } . Production = production_name "=" [ Expression ] "." . Expression = Alternative { "|" Alternative } . Alternative = Term { Term } . Term = production_name | _token | Range | Group | Option | Repetition . Range = _token "…" _token . Group = "(" Expression ")" . Option = "[" Expression "]" . Repetition = "{" Expression "}" . """ ast = EBNFParser.matchAll(grammar, `Grammar) EBNFTranslator.match(ast, `trans) ometa Parser <: Scanner { // Grammar = Production { Production } . Grammar = Production Production*, // Production = production_name "=" [ Expression ] "." . Production = scan("production_name") "=" Expression? ".", // Expression = Alternative { "|" Alternative } . Expression = Alternative ("|" Alternative)*, // Alternative = Term { Term } . Alternative = Term Term*, // Term = production_name | _token | Range | Group | Option | Repetition . Term = scan("production_name") | scan("_token") | Range | Group | Option | Repetition, // Range = _token "…" _token . Range = scan("_token") "\u2026" scan("_token"), // Group = "(" Expression ")" . Group = "(" Expression ")", // Option = "[" Expression "]" . Option = "[" Expression "]", // Repetition = "{" Expression "}" . Repetition = "{" Expression "}" } EBNFTranslator.match([`Production, [`parsing_name, `Grammar], [`Expression, [`Alternative, [`Term, [`parsing_name, `Production]], [`Term, [`Repetition, [`Expression, [`Alternative, [`Term, [`parsing_name, `Production]]]]]]]], 'this line'], `trans) EBNFTranslator.match([`Production, [`parsing_name, `Grammar], [`Expression, [`Alternative, [`Term, [`parsing_name, `Production]]]], 'this line'], `trans) EBNFTranslator.match('comment 1\n comment 2\n\n3', `comment_lines) EBNFTranslator.match('this line', `comment_lines) EBNFTranslator.match([`Expression, [`Alternative, [`Term, [`parsing_name, `Production]], [`Term, [`Repetition, [`Expression, [`Alternative, [`Term, [`parsing_name, `Production]]]]]]]], `trans) EBNFTranslator.match([`Repetition, [`Expression, [`Alternative, [`Term, [`parsing_name, `Production]]]]], `trans) EBNFTranslator.match([`parsing_name, `Grammar], `trans) ometa EBNFParser2 <: Scanner { // Grammar = Production { Production } . Grammar = Production Production*, // Production = production_name "=" [ Expression ] "." . Production = production_name "=" Expression? ".", // Expression = Alternative { "|" Alternative } . Expression = Alternative ("|" Alternative)*, // Alternative = Term { Term } . Alternative = Term Term*, // Term = production_name | _token | Range | Group | Option | Repetition . Term = production_name | _token | Range | Group | Option | Repetition, // Range = _token "…" _token . Range = _token "\u2026" _token, // Group = "(" Expression ")" . Group = "(" Expression ")", // Option = "[" Expression "]" . Option = "[" Expression "]", // Repetition = "{" Expression "}" . Repetition = "{" Expression "}" } EBNFParser2.matchAll(grammar, `Grammar) GoGrammar = """ decimal_digit = "0" … "9" . octal_digit = "0" … "7" . hex_digit = "0" … "9" | "A" … "F" | "a" … "f" . letter = unicode_letter | "_" . identifier = letter { letter | unicode_digit } . int_lit = decimal_lit | octal_lit | hex_lit . decimal_lit = ( "1" … "9" ) { decimal_digit } . octal_lit = "0" { octal_digit } . hex_lit = "0" ( "x" | "X" ) hex_digit { hex_digit } . float_lit = decimals "." [ decimals ] [ exponent ] | decimals exponent | "." decimals [ exponent ] . decimals = decimal_digit { decimal_digit } . exponent = ( "e" | "E" ) [ "+" | "-" ] decimals . imaginary_lit = (decimals | float_lit) "i" . char_lit = "'" ( unicode_value | byte_value ) "'" . unicode_value = unicode_char | little_u_value | big_u_value | escaped_char . byte_value = octal_byte_value | hex_byte_value . octal_byte_value = `\` octal_digit octal_digit octal_digit . hex_byte_value = `\` "x" hex_digit hex_digit . little_u_value = `\` "u" hex_digit hex_digit hex_digit hex_digit . big_u_value = `\` "U" hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit . escaped_char = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `"` ) . string_lit = raw_string_lit | interpreted_string_lit . raw_string_lit = "`" { unicode_char | newline } "`" . interpreted_string_lit = `"` { unicode_value | byte_value } `"` . Type = TypeName | TypeLit | "(" Type ")" . TypeName = QualifiedIdent . TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | SliceType | MapType | ChannelType . ArrayType = "[" ArrayLength "]" ElementType . ArrayLength = Expression . ElementType = Type . SliceType = "[" "]" ElementType . StructType = "struct" "{" { FieldDecl ";" } "}" . FieldDecl = (IdentifierList Type | AnonymousField) [ Tag ] . AnonymousField = [ "*" ] TypeName . Tag = string_lit . PointerType = "*" BaseType . BaseType = Type . FunctionType = "func" Signature . Signature = Parameters [ Result ] . Result = Parameters | Type . Parameters = "(" [ ParameterList [ "," ] ] ")" . ParameterList = ParameterDecl { "," ParameterDecl } . ParameterDecl = [ IdentifierList ] [ "..." ] Type . InterfaceType = "interface" "{" { MethodSpec ";" } "}" . MethodSpec = MethodName Signature | InterfaceTypeName . MethodName = identifier . InterfaceTypeName = TypeName . MapType = "map" "[" KeyType "]" ElementType . KeyType = Type . ChannelType = ( "chan" [ "<-" ] | "<-" "chan" ) ElementType . Block = "{" { Statement ";" } "}" . Declaration = ConstDecl | TypeDecl | VarDecl . TopLevelDecl = Declaration | FunctionDecl | MethodDecl . ConstDecl = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) . ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] . IdentifierList = identifier { "," identifier } . ExpressionList = Expression { "," Expression } . TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) . TypeSpec = identifier Type . VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) . VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) . ShortVarDecl = IdentifierList ":=" ExpressionList . FunctionDecl = "func" identifier Signature [ Body ] . Body = Block . MethodDecl = "func" Receiver MethodName Signature [ Body ] . Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" . BaseTypeName = identifier . Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" . Literal = BasicLit | CompositeLit | FunctionLit . BasicLit = int_lit | float_lit | imaginary_lit | char_lit | string_lit . QualifiedIdent = [ PackageName "." ] identifier . CompositeLit = LiteralType LiteralValue . LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | SliceType | MapType | TypeName . LiteralValue = "{" [ ElementList [ "," ] ] "}" . ElementList = Element { "," Element } . Element = [ Key ":" ] Value . Key = FieldName | ElementIndex . FieldName = identifier . ElementIndex = Expression . Value = Expression | LiteralValue . FunctionLit = FunctionType Body . PrimaryExpr = Operand | Conversion | BuiltinCall | PrimaryExpr Selector | PrimaryExpr Index | PrimaryExpr Slice | PrimaryExpr TypeAssertion | PrimaryExpr Call . Selector = "." identifier . Index = "[" Expression "]" . Slice = "[" [ Expression ] ":" [ Expression ] "]" . TypeAssertion = "." "(" Type ")" . Call = "(" [ ArgumentList [ "," ] ] ")" . ArgumentList = ExpressionList [ "..." ] . Expression = UnaryExpr | Expression binary_op UnaryExpr . UnaryExpr = PrimaryExpr | unary_op UnaryExpr . binary_op = "||" | "&&" | rel_op | add_op | mul_op . rel_op = "==" | "!=" | "<" | "<=" | ">" | ">=" . add_op = "+" | "-" | "|" | "^" . mul_op = "*" | "/" | "%" | "<<" | ">>" | "&" | "&^" . unary_op = "+" | "-" | "!" | "^" | "*" | "&" | "<-" . MethodExpr = ReceiverType "." MethodName . ReceiverType = TypeName | "(" "*" TypeName ")" . Conversion = Type "(" Expression ")" . Statement = Declaration | LabeledStmt | SimpleStmt | GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt | FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt | DeferStmt . SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl . EmptyStmt = . LabeledStmt = Label ":" Statement . Label = identifier . ExpressionStmt = Expression . SendStmt = Channel "<-" Expression . Channel = Expression . IncDecStmt = Expression ( "++" | "--" ) . Assignment = ExpressionList assign_op ExpressionList . assign_op = [ add_op | mul_op ] "=" . IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] . SwitchStmt = ExprSwitchStmt | TypeSwitchStmt . ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ExprCaseClause } "}" . ExprCaseClause = ExprSwitchCase ":" { Statement ";" } . ExprSwitchCase = "case" ExpressionList | "default" . TypeSwitchStmt = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" . TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" . TypeCaseClause = TypeSwitchCase ":" { Statement ";" } . TypeSwitchCase = "case" TypeList | "default" . TypeList = Type { "," Type } . ForStmt = "for" [ Condition | ForClause | RangeClause ] Block . Condition = Expression . ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] . InitStmt = SimpleStmt . PostStmt = SimpleStmt . RangeClause = Expression [ "," Expression ] ( "=" | ":=" ) "range" Expression . GoStmt = "go" Expression . SelectStmt = "select" "{" { CommClause } "}" . CommClause = CommCase ":" { Statement ";" } . CommCase = "case" ( SendStmt | RecvStmt ) | "default" . RecvStmt = [ Expression [ "," Expression ] ( "=" | ":=" ) ] RecvExpr . RecvExpr = Expression . ReturnStmt = "return" [ ExpressionList ] . BreakStmt = "break" [ Label ] . ContinueStmt = "continue" [ Label ] . GotoStmt = "goto" Label . FallthroughStmt = "fallthrough" . DeferStmt = "defer" Expression . BuiltinCall = identifier "(" [ BuiltinArgs [ "," ] ] ")" . BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList . SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } . PackageClause = "package" PackageName . PackageName = identifier . ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) . ImportSpec = [ "." | PackageName ] ImportPath . ImportPath = string_lit . """ go_ast = EBNFParser.matchAll(GoGrammar, `Grammar) EBNFTranslator.match(go_ast, `trans) ometa GoBaseParser <: Scanner { // decimal_digit = "0" … "9" . decimal_digit = charRange('0', '9'), // octal_digit = "0" … "7" . octal_digit = charRange('0', '7'), // hex_digit = "0" … "9" | "A" … "F" | "a" … "f" . hex_digit = charRange('0', '9') | charRange('A', 'F') | charRange('a', 'f'), // letter = unicode_letter | "_" . letter = unicode_letter | '_', // identifier = letter { letter | unicode_digit } . identifier = letter (letter | unicode_digit)*, // int_lit = decimal_lit | octal_lit | hex_lit . int_lit = decimal_lit | octal_lit | hex_lit, // decimal_lit = ( "1" … "9" ) { decimal_digit } . decimal_lit = (charRange('1', '9')) decimal_digit*, // octal_lit = "0" { octal_digit } . octal_lit = '0' octal_digit*, // hex_lit = "0" ( "x" | "X" ) hex_digit { hex_digit } . hex_lit = '0' ('x' | 'X') hex_digit hex_digit*, // float_lit = decimals "." [ decimals ] [ exponent ] | // decimals exponent | // "." decimals [ exponent ] . float_lit = decimals '.' decimals? exponent? | decimals exponent | '.' decimals exponent?, // decimals = decimal_digit { decimal_digit } . decimals = decimal_digit decimal_digit*, // exponent = ( "e" | "E" ) [ "+" | "-" ] decimals . exponent = ('e' | 'E') ('+' | '-')? decimals, // imaginary_lit = (decimals | float_lit) "i" . imaginary_lit = (decimals | float_lit) 'i', // char_lit = "'" ( unicode_value | byte_value ) "'" . char_lit = '\'' (unicode_value | byte_value) '\'', // unicode_value = unicode_char | little_u_value | big_u_value | escaped_char . unicode_value = unicode_char | little_u_value | big_u_value | escaped_char, // byte_value = octal_byte_value | hex_byte_value . byte_value = octal_byte_value | hex_byte_value, // octal_byte_value = `\` octal_digit octal_digit octal_digit . octal_byte_value = '\\' octal_digit octal_digit octal_digit, // hex_byte_value = `\` "x" hex_digit hex_digit . hex_byte_value = '\\' 'x' hex_digit hex_digit, // little_u_value = `\` "u" hex_digit hex_digit hex_digit hex_digit . little_u_value = '\\' 'u' hex_digit hex_digit hex_digit hex_digit, // big_u_value = `\` "U" hex_digit hex_digit hex_digit hex_digit // hex_digit hex_digit hex_digit hex_digit . big_u_value = '\\' 'U' hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit, // escaped_char = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `"` ) . escaped_char = '\\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\\' | '\'' | '\"'), // string_lit = raw_string_lit | interpreted_string_lit . string_lit = raw_string_lit | interpreted_string_lit, // raw_string_lit = "`" { unicode_char | newline } "`" . raw_string_lit = '`' (~'`' (unicode_char | newline))* '`', // interpreted_string_lit = `"` { unicode_value | byte_value } `"` . interpreted_string_lit = '\"' (~'\"' (unicode_value | byte_value))* '\"', // Type = TypeName | TypeLit | "(" Type ")" . Type = TypeName | TypeLit | "(" Type ")", // TypeName = QualifiedIdent . TypeName = QualifiedIdent, // TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | // SliceType | MapType | ChannelType . TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | SliceType | MapType | ChannelType, // ArrayType = "[" ArrayLength "]" ElementType . ArrayType = "[" ArrayLength "]" ElementType, // ArrayLength = Expression . ArrayLength = Expression, // ElementType = Type . ElementType = Type, // SliceType = "[" "]" ElementType . SliceType = "[" "]" ElementType, // StructType = "struct" "{" { FieldDecl ";" } "}" . StructType = "struct" "{" (FieldDecl ";")* "}", // FieldDecl = (IdentifierList Type | AnonymousField) [ Tag ] . FieldDecl = (IdentifierList Type | AnonymousField) Tag?, // AnonymousField = [ "*" ] TypeName . AnonymousField = "*"? TypeName, // Tag = string_lit . Tag = scan("string_lit"), // PointerType = "*" BaseType . PointerType = "*" BaseType, // BaseType = Type . BaseType = Type, // FunctionType = "func" Signature . FunctionType = "func" Signature, // Signature = Parameters [ Result ] . Signature = Parameters Result?, // Result = Parameters | Type . Result = Parameters | Type, // Parameters = "(" [ ParameterList [ "," ] ] ")" . Parameters = "(" (ParameterList ","?)? ")", // ParameterList = ParameterDecl { "," ParameterDecl } . ParameterList = ParameterDecl ("," ParameterDecl)*, // ParameterDecl = [ IdentifierList ] [ "..." ] Type . ParameterDecl = IdentifierList? "..."? Type, // InterfaceType = "interface" "{" { MethodSpec ";" } "}" . InterfaceType = "interface" "{" (MethodSpec ";")* "}", // MethodSpec = MethodName Signature | InterfaceTypeName . MethodSpec = MethodName Signature | InterfaceTypeName, // MethodName = identifier . MethodName = scan("identifier"), // InterfaceTypeName = TypeName . InterfaceTypeName = TypeName, // MapType = "map" "[" KeyType "]" ElementType . MapType = "map" "[" KeyType "]" ElementType, // KeyType = Type . KeyType = Type, // ChannelType = ( "chan" [ "<-" ] | "<-" "chan" ) ElementType . ChannelType = ("chan" "<-"? | "<-" "chan") ElementType, // Block = "{" { Statement ";" } "}" . Block = "{" (Statement ";")* "}", // Declaration = ConstDecl | TypeDecl | VarDecl . Declaration = ConstDecl | TypeDecl | VarDecl, // TopLevelDecl = Declaration | FunctionDecl | MethodDecl . TopLevelDecl = Declaration | FunctionDecl | MethodDecl, // ConstDecl = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) . ConstDecl = "const" (ConstSpec | "(" (ConstSpec ";")* ")"), // ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] . ConstSpec = IdentifierList (Type? "=" ExpressionList)?, // IdentifierList = identifier { "," identifier } . IdentifierList = scan("identifier") ("," scan("identifier"))*, // ExpressionList = Expression { "," Expression } . ExpressionList = Expression ("," Expression)*, // TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) . TypeDecl = "type" (TypeSpec | "(" (TypeSpec ";")* ")"), // TypeSpec = identifier Type . TypeSpec = scan("identifier") Type, // VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) . VarDecl = "var" (VarSpec | "(" (VarSpec ";")* ")"), // VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) . VarSpec = IdentifierList (Type ("=" ExpressionList)? | "=" ExpressionList), // ShortVarDecl = IdentifierList ":=" ExpressionList . ShortVarDecl = IdentifierList ":=" ExpressionList, // FunctionDecl = "func" identifier Signature [ Body ] . FunctionDecl = "func" scan("identifier") Signature Body?, // Body = Block . Body = Block, // MethodDecl = "func" Receiver MethodName Signature [ Body ] . MethodDecl = "func" Receiver MethodName Signature Body?, // Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" . Receiver = "(" scan("identifier")? "*"? BaseTypeName ")", // BaseTypeName = identifier . BaseTypeName = scan("identifier"), // Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" . Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")", // Literal = BasicLit | CompositeLit | FunctionLit . Literal = BasicLit | CompositeLit | FunctionLit, // BasicLit = int_lit | float_lit | imaginary_lit | char_lit | string_lit . BasicLit = scan("int_lit") | scan("float_lit") | scan("imaginary_lit") | scan("char_lit") | scan("string_lit"), // QualifiedIdent = [ PackageName "." ] identifier . QualifiedIdent = (PackageName ".")? scan("identifier"), // CompositeLit = LiteralType LiteralValue . CompositeLit = LiteralType LiteralValue, // LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | // SliceType | MapType | TypeName . LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | SliceType | MapType | TypeName, // LiteralValue = "{" [ ElementList [ "," ] ] "}" . LiteralValue = "{" (ElementList ","?)? "}", // ElementList = Element { "," Element } . ElementList = Element ("," Element)*, // Element = [ Key ":" ] Value . Element = (Key ":")? Value, // Key = FieldName | ElementIndex . Key = FieldName | ElementIndex, // FieldName = identifier . FieldName = scan("identifier"), // ElementIndex = Expression . ElementIndex = Expression, // Value = Expression | LiteralValue . Value = Expression | LiteralValue, // FunctionLit = FunctionType Body . FunctionLit = FunctionType Body, // PrimaryExpr = // Operand | // Conversion | // BuiltinCall | // PrimaryExpr Selector | // PrimaryExpr Index | // PrimaryExpr Slice | // PrimaryExpr TypeAssertion | // PrimaryExpr Call . PrimaryExpr = Operand | Conversion | BuiltinCall | PrimaryExpr Selector | PrimaryExpr Index | PrimaryExpr Slice | PrimaryExpr TypeAssertion | PrimaryExpr Call, // Selector = "." identifier . Selector = "." scan("identifier"), // Index = "[" Expression "]" . Index = "[" Expression "]", // Slice = "[" [ Expression ] ":" [ Expression ] "]" . Slice = "[" Expression? ":" Expression? "]", // TypeAssertion = "." "(" Type ")" . TypeAssertion = "." "(" Type ")", // Call = "(" [ ArgumentList [ "," ] ] ")" . Call = "(" (ArgumentList ","?)? ")", // ArgumentList = ExpressionList [ "..." ] . ArgumentList = ExpressionList "..."?, // Expression = UnaryExpr | Expression binary_op UnaryExpr . Expression = UnaryExpr | Expression scan("binary_op") UnaryExpr, // UnaryExpr = PrimaryExpr | unary_op UnaryExpr . UnaryExpr = PrimaryExpr | scan("unary_op") UnaryExpr, // binary_op = "||" | "&&" | rel_op | add_op | mul_op . binary_op = '||' | '&&' | rel_op | add_op | mul_op, // rel_op = "==" | "!=" | "<" | "<=" | ">" | ">=" . rel_op = '==' | '!=' | '<' | '<=' | '>' | '>=', // add_op = "+" | "-" | "|" | "^" . add_op = '+' | '-' | '|' | '^', // mul_op = "*" | "/" | "%" | "<<" | ">>" | "&" | "&^" . mul_op = '*' | '/' | '%' | '<<' | '>>' | '&' | '&^', // unary_op = "+" | "-" | "!" | "^" | "*" | "&" | "<-" . unary_op = '+' | '-' | '!' | '^' | '*' | '&' | '<-', // MethodExpr = ReceiverType "." MethodName . MethodExpr = ReceiverType "." MethodName, // ReceiverType = TypeName | "(" "*" TypeName ")" . ReceiverType = TypeName | "(" "*" TypeName ")", // Conversion = Type "(" Expression ")" . Conversion = Type "(" Expression ")", // Statement = // Declaration | LabeledStmt | SimpleStmt | // GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt | // FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt | // DeferStmt . Statement = Declaration | LabeledStmt | SimpleStmt | GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt | FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt | DeferStmt, // SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl . SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl, // EmptyStmt = . EmptyStmt = empty, // LabeledStmt = Label ":" Statement . LabeledStmt = Label ":" Statement, // Label = identifier . Label = scan("identifier"), // ExpressionStmt = Expression . ExpressionStmt = Expression, // SendStmt = Channel "<-" Expression . SendStmt = Channel "<-" Expression, // Channel = Expression . Channel = Expression, // IncDecStmt = Expression ( "++" | "--" ) . IncDecStmt = Expression ("++" | "--"), // Assignment = ExpressionList assign_op ExpressionList . Assignment = ExpressionList scan("assign_op") ExpressionList, // assign_op = [ add_op | mul_op ] "=" . assign_op = (add_op | mul_op)? '=', // IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] . IfStmt = "if" (SimpleStmt ";")? Expression Block ("else" (IfStmt | Block))?, // SwitchStmt = ExprSwitchStmt | TypeSwitchStmt . SwitchStmt = ExprSwitchStmt | TypeSwitchStmt, // ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ExprCaseClause } "}" . ExprSwitchStmt = "switch" (SimpleStmt ";")? Expression? "{" ExprCaseClause* "}", // ExprCaseClause = ExprSwitchCase ":" { Statement ";" } . ExprCaseClause = ExprSwitchCase ":" (Statement ";")*, // ExprSwitchCase = "case" ExpressionList | "default" . ExprSwitchCase = "case" ExpressionList | "default", // TypeSwitchStmt = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" . TypeSwitchStmt = "switch" (SimpleStmt ";")? TypeSwitchGuard "{" TypeCaseClause* "}", // TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" . TypeSwitchGuard = (scan("identifier") ":=")? PrimaryExpr "." "(" "type" ")", // TypeCaseClause = TypeSwitchCase ":" { Statement ";" } . TypeCaseClause = TypeSwitchCase ":" (Statement ";")*, // TypeSwitchCase = "case" TypeList | "default" . TypeSwitchCase = "case" TypeList | "default", // TypeList = Type { "," Type } . TypeList = Type ("," Type)*, // ForStmt = "for" [ Condition | ForClause | RangeClause ] Block . ForStmt = "for" (Condition | ForClause | RangeClause)? Block, // Condition = Expression . Condition = Expression, // ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] . ForClause = InitStmt? ";" Condition? ";" PostStmt?, // InitStmt = SimpleStmt . InitStmt = SimpleStmt, // PostStmt = SimpleStmt . PostStmt = SimpleStmt, // RangeClause = Expression [ "," Expression ] ( "=" | ":=" ) "range" Expression . RangeClause = Expression ("," Expression)? ("=" | ":=") "range" Expression, // GoStmt = "go" Expression . GoStmt = "go" Expression, // SelectStmt = "select" "{" { CommClause } "}" . SelectStmt = "select" "{" CommClause* "}", // CommClause = CommCase ":" { Statement ";" } . CommClause = CommCase ":" (Statement ";")*, // CommCase = "case" ( SendStmt | RecvStmt ) | "default" . CommCase = "case" (SendStmt | RecvStmt) | "default", // RecvStmt = [ Expression [ "," Expression ] ( "=" | ":=" ) ] RecvExpr . RecvStmt = (Expression ("," Expression)? ("=" | ":="))? RecvExpr, // RecvExpr = Expression . RecvExpr = Expression, // ReturnStmt = "return" [ ExpressionList ] . ReturnStmt = "return" ExpressionList?, // BreakStmt = "break" [ Label ] . BreakStmt = "break" Label?, // ContinueStmt = "continue" [ Label ] . ContinueStmt = "continue" Label?, // GotoStmt = "goto" Label . GotoStmt = "goto" Label, // FallthroughStmt = "fallthrough" . FallthroughStmt = "fallthrough", // DeferStmt = "defer" Expression . DeferStmt = "defer" Expression, // BuiltinCall = identifier "(" [ BuiltinArgs [ "," ] ] ")" . BuiltinCall = scan("identifier") "(" (BuiltinArgs ","?)? ")", // BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList . BuiltinArgs = Type ("," ExpressionList)? | ExpressionList, // SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } . SourceFile = PackageClause ";" (ImportDecl ";")* (TopLevelDecl ";")*, // PackageClause = "package" PackageName . PackageClause = "package" PackageName, // PackageName = identifier . PackageName = scan("identifier"), // ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) . ImportDecl = "import" (ImportSpec | "(" (ImportSpec ";")* ")"), // ImportSpec = [ "." | PackageName ] ImportPath . ImportSpec = ("." | PackageName)? ImportPath, // ImportPath = string_lit . ImportPath = scan("string_lit") } ometa GoParser <: GoBaseParser { // Avoid ExpressionStmt preventing a match of a larger statement ExpressionStmt = ^ExpressionStmt &";", // Require a real semicolon after any empty statement EmptyStmt = ^EmptyStmt &real_semicolon, PrimaryExpr = (Operand | Conversion | BuiltinCall) (Selector | Index | Slice | TypeAssertion | Call)*, Operand = ~BuiltinCall ^Operand, BuiltinCall = &(scan("builtin") "(") ^BuiltinCall, identifier = ~keyword ^identifier, keyword = <^identifier>:id ?(this.keywords.indexOf(id)>0), builtin = <^identifier>:id ?(this.builtins.indexOf(id)>0), PackageClause = <^PackageClause>, ImportDecl = <^ImportDecl>, TopLevelDecl = <^TopLevelDecl>, SourceFile = !(o={}) PackageClause:p {o.p=p} ";" (ImportDecl:i ";" ->i)*:i {o.i=i} (TopLevelDecl:d ";" ->d)*:d {o.d=d} -> o, e = 0 } GoParser.initialize = function() { this.keywords = [ 'break' , 'continue' , 'fallthrough' , 'return' , 'case:' , 'chan' , 'const' , 'default' , 'defer' , 'else' , 'for' , 'func' , 'go' , 'goto' , 'if' , 'import' , 'interface' , 'map' , 'package' , 'range' , 'select' , 'struct' , 'switch' , 'type' , 'var' ]; this.builtins = [ 'append' , 'cap' , 'close' , 'complex' , 'copy' , 'imag' , 'len' , 'make' , 'new' , 'panic' , 'print' , 'println' , 'real' , 'recover' ]; } gocode = """ package main import "fmt" func main() { var x, y, z int = 1, 2, 3 c, python, java := true, false, "no!" fmt.Println(x, y, z, c, python, java) } """ GoParser.matchAll(gocode, `SourceFile)