% $Id: SyntaxSummary.tex 21104 2010-03-08 13:49:27Z odersky $ \chapter{Scala Syntax Summary}\label{sec:syntax} \todo{introduce SeqPattern syntax} The lexical syntax of Scala is given by the following grammar in EBNF form. {\small \begin{lstlisting} upper ::= `A' | $\cdots$ | `Z' | `$\Dollar$' | `_' $\mbox{\rm\em and Unicode category Lu}$ lower ::= `a' | $\cdots$ | `z' $\mbox{\rm\em and Unicode category Ll}$ letter ::= upper | lower $\mbox{\rm\em and Unicode categories Lo, Lt, Nl}$ digit ::= `0' | $\cdots$ | `9' opchar ::= $\mbox{\rm\em ``all other characters in \U{0020-007F} and Unicode}$ $\mbox{\rm\em categories Sm, So except parentheses ([{}]) and periods''}$ op ::= opchar {opchar} varid ::= lower idrest alphaid ::= upper idrest | varid plainid ::= alphaid | op id ::= plainid | `\`' stringLit `\`' | INT // interpolation id, only for quasi-quotes idrest ::= {letter | digit} [`_' op] integerLiteral ::= (decimalNumeral | hexNumera) [`L' | `l'] decimalNumeral ::= `0' | nonZeroDigit {digit} hexNumeral ::= `0' `x' hexDigit {hexDigit} digit ::= `0' | nonZeroDigit nonZeroDigit ::= `1' | $\cdots$ | `9' octalDigit ::= `0' | $\cdots$ | `7' floatingPointLiteral ::= digit {digit} `.' {digit} [exponentPart] [floatType] | `.' digit {digit} [exponentPart] [floatType] | digit {digit} exponentPart [floatType] | digit {digit} [exponentPart] floatType exponentPart ::= (`E' | `e') [`+' | `-'] digit {digit} floatType ::= `F' | `f' | `D' | `d' booleanLiteral ::= `true' | `false' characterLiteral ::= `\'' printableChar `\'' | `\'' charEscapeSeq `\'' stringLiteral ::= `"' {stringElement} `"' | `"""' {[`"'] [`"'] char \ `"'} {`"'} `"""' stringElement ::= printableChar \ (`"' | `\') | charEscapeSeq charEscapeSeq ::= `\b' | `\n' | `\t' | `\f' | `\r' | `"' | `'' | `\\' processedStringLiteral ::= alphaid`"' {printableChar \ (`"' | `$') | escape} `"' | alphaid `"""' {[`"'] [`"'] char \ (`"' | `$') | escape} {`"'} `"""' escape ::= `$$' \comment{$} | `$' letter { letter | digit } | `{' Block [`;' whiteSpace stringFormat whiteSpace] `}' stringFormat ::= {printableChar \ (`"' | `}' | ` ' | `\t' | `\n')} whiteSpace ::= {` ' | `\t'} symbolLiteral ::= `'' plainid comment ::= `/*' $\mbox{\rm\em ``any sequence of characters''}$ `*/' | `//' $\mbox{\rm\em ``any sequence of characters up to end of line''}$ nl ::= $\mbox{\rm\em ``new line character''}$ semi ::= `;' | nl {nl} \end{lstlisting}} The context-free syntax of Scala is given by the following EBNF grammar. {\small \begin{lstlisting} SimpleLiteral ::= [`-'] integerLiteral | [`-'] floatingPointLiteral | booleanLiteral | characterLiteral | stringLiteral Literal ::= SimpleLiteral | processedStringLiteral | symbolLiteral | `null' QualId ::= id {`.' id} ids ::= id {`,' id} Path ::= StableId | [id `.'] `this' StableId ::= id | Path `.' id | [id '.'] `super' [ClassQualifier] `.' id ClassQualifier ::= `[' id `]' Type ::= FunArgTypes `=>' Type Function(ts, t) | HkTypeParamClause `->' Type TypeLambda(ps, t) | InfixType FunArgTypes ::= InfixType | `(' [ FunArgType {`,' FunArgType } ] `)' InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2) RefinedType ::= WithType {[nl] Refinement} RefinedTypeTree(t, ds) WithType ::= AnnotType {`with' AnnotType} (deprecated) AnnotType ::= SimpleType {Annotation} Annotated(t, annot) SimpleType ::= SimpleType (TypeArgs | NamedTypeArgs) AppliedTypeTree(t, args) | SimpleType `#' id Select(t, name) | StableId | Path `.' `type' SingletonTypeTree(p) | `(' ArgTypes ')' Tuple(ts) | `_' TypeBounds | Refinement RefinedTypeTree(EmptyTree, refinement) | SimpleLiteral SingletonTypeTree(l) ArgTypes ::= Type {`,' Type} | NamedTypeArg {`,' NamedTypeArg } FunArgType ::= Type | `=>' Type PrefixOp(=>, t) ParamType ::= [`=>'] ParamValueType ParamValueType ::= Type [`*'] PostfixOp(t, "*") TypeArgs ::= `[' ArgTypes `]' ts NamedTypeArg ::= id `=' Type NamedArg(id, t) NamedTypeArgs ::= `[' NamedTypeArg {`,' NamedTypeArg} `]' nts Refinement ::= `{' [Dcl] {semi [Dcl]} `}' ds TypeBounds ::= [`>:' Type] [`<: Type] | INT TypeBoundsTree(lo, hi) TypeParamBounds ::= TypeBounds {`<%' Type} {`:' Type} ContextBounds(typeBounds, tps) Expr ::= FunParams `=>' Expr Function(args, expr), Function(ValDef([implicit], id, TypeTree(), EmptyTree), expr) FunParams ::= Bindings | [`implicit'] id | `_' ExprInParens ::= PostfixExpr `:' Type | Expr BlockResult ::= (FunParams | [`implicit'] id `:' InfixType) `=>' Block | Expr1 Expr1 ::= `if' `(' Expr `)' {nl} Expr [[semi] else Expr] If(Parens(cond), thenp, elsep?) | `if' Expr `then' Expr [[semi] else Expr] If(cond, thenp, elsep?) | `while' `(' Expr `)' {nl} Expr WhileDo(Parens(cond), body) | `while' Expr `do' Expr WhileDo(cond, body) | `do' Expr [semi] `while' Expr DoWhile(expr, cond) | `try' Expr Catches [`finally' Expr] Try(expr, catches, expr?) | `try' Expr [`finally' Expr] Try(expr, Nil, expr?) | `throw' Expr Throw(expr) | `return' [Expr] Return(expr?) | ForExpr | [SimpleExpr `.'] id `=' Expr Assign(expr, expr) | SimpleExpr1 ArgumentExprs `=' Expr Assign(expr, expr) | PostfixExpr [Ascription] | PostfixExpr `match' `{' CaseClauses `}' Match(expr, cases) -- point on match Ascription ::= `:' InfixType Typed(expr, tp) | `:' Annotation {Annotation} Typed(expr, Annotated(EmptyTree, annot)*) Catches ::= `catch' Expr PostfixExpr ::= InfixExpr [id] PostfixOp(expr, op) InfixExpr ::= PrefixExpr | InfixExpr id [nl] InfixExpr InfixOp(expr, op, expr) PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr PrefixOp(expr, op) SimpleExpr ::= `new' Template New(templ) | BlockExpr | SimpleExpr1 [`_'] PostfixOp(expr, _) SimpleExpr1 ::= Literal | Path | `_' | `(' ExprsInParens `)' Parens(exprs) | SimpleExpr `.' id Select(expr, id) | SimpleExpr (TypeArgs | NamedTypeArgs) TypeApply(expr, args) | SimpleExpr1 ArgumentExprs Apply(expr, args) | XmlExpr ExprsInParens ::= ExprInParens {`,' ExprInParens} ParArgumentExprs ::= `(' [ExprsInParens] `)' exprs | `(' [ExprsInParens `,'] PostfixExpr `:' `_' `*' ')' exprs :+ Typed(expr, Ident(wildcardStar)) ArgumentExprs ::= ParArgumentExprs | [nl] BlockExpr BlockExpr ::= `{' CaseClauses `}' Match(EmptyTree, cases) | `{' Block `}' block // starts at { Block ::= {BlockStat semi} [BlockResult] Block(stats, expr?) BlockStat ::= Import | {Annotation} [`implicit' | `lazy'] Def | {Annotation} {LocalModifier} TmplDef | Expr1 | ResultExpr ::= Expr1 | (Bindings | ([`implicit'] id | `_') `:' ) `=>' Block Function(args, block) // block starts at => ForExpr ::= `for' (`(' Enumerators `)' | `{' Enumerators `}') ForYield(enums, expr) {nl} [`yield'] Expr ForDo(enums, expr) | `for' Enumerators (`do' Expr | `yield' Expr) Enumerators ::= Generator {semi Enumerator | Guard} Enumerator ::= Generator | Guard | Pattern1 `=' Expr GenAlias(pat, expr) Generator ::= Pattern1 `<-' Expr GenFrom(pat, expr) Guard ::= `if' PostfixExpr CaseClauses ::= CaseClause { CaseClause } CaseClause ::= `case' (Pattern [Guard] `=>' Block | INT) CaseDef(pat, guard?, block) // block starts at => Pattern ::= Pattern1 { `|' Pattern1 } Alternative(pats) Pattern1 ::= PatVar `:' RefinedType Bind(name, Typed(Ident(wildcard), tpe)) | Pattern2 Pattern2 ::= [varid `@'] InfixPattern Bind(name, pat) InfixPattern ::= SimplePattern { id [nl] SimplePattern } InfixOp(pat, op, pat) SimplePattern ::= PatVar Ident(wildcard) | Literal Bind(name, Ident(wildcard)) | `(' [Patterns] `)' Parens(pats) Tuple(pats) | XmlPattern | SimplePattern1 [TypeArgs] [ArgumentPatterns] SimplePattern1 ::= Path | `{' Block `}' | SimplePattern1 `.' id PatVar ::= varid | `_' Patterns ::= Pattern [`,' Pattern] ArgumentPatterns ::= `(' [Patterns] `)' Apply(fn, pats) | `(' [Patterns `,'] Pattern2 `:' `_' `*' ') ClsTypeParamClause::= `[' ClsTypeParam {`,' ClsTypeParam} `]' ClsTypeParam ::= {Annotation} [{Modifier} type] [`+' | `-'] TypeDef(Modifiers, name, tparams, bounds) id [HkTypeParamClause] TypeParamBounds Bound(below, above, context) DefTypeParamClause::= `[' DefTypeParam {`,' DefTypeParam} `]' DefTypeParam ::= {Annotation} id [HkTypeParamClause] TypeParamBounds TypTypeParamCaluse::= `[' TypTypeParam {`,' TypTypeParam} `]' TypTypeParam ::= {Annotation} id [HkTypeParamClause] TypeBounds HkTypeParamClause ::= `[' HkTypeParam {`,' HkTypeParam} `]' HkTypeParam ::= {Annotation} ['+' | `-'] (Id[HkTypeParamClause] | `_') TypeBounds ClsParamClauses ::= {ClsParamClause} [[nl] `(' `implicit' ClsParams `)'] ClsParamClause ::= [nl] `(' [ClsParams] ')' ClsParams ::= ClsParam {`' ClsParam} ClsParam ::= {Annotation} [{Modifier} (`val' | `var') | `inline'] Param ValDef(mods, id, tpe, expr) -- point of mods on val/var Param ::= id `:' ParamType [`=' Expr] | INT DefParamClauses ::= {DefParamClause} [[nl] `(' `implicit' DefParams `)'] DefParamClause ::= [nl] `(' [DefParams] ')' DefParams ::= DefParam {`,' DefParam} DefParam ::= {Annotation} [`inline'] Param ValDef(mods, id, tpe, expr) -- point of mods at id. Bindings ::= `(' Binding {`,' Binding `)' bindings Binding ::= (id | `_') [`:' Type] ValDef(_, id, tpe, EmptyTree) Modifier ::= LocalModifier | AccessModifier | `override' LocalModifier ::= `abstract' | `final' | `sealed' | `implicit' | `lazy' AccessModifier ::= (`private' | `protected') [AccessQualifier] AccessQualifier ::= `[' (id | `this') `]' Annotation ::= `@' SimpleType {ParArgumentExprs} Apply(tpe, args) TemplateBody ::= [nl] `{' [SelfType] TemplateStat {semi TemplateStat} `} (self, stats) TemplateStat ::= Import | {Annotation [nl]} {Modifier} Def | {Annotation [nl]} {Modifier} Dcl | Expr1 | SelfType ::= id [`:' InfixType] `=>' ValDef(_, name, tpt, _) | `this' `:' InfixType `=> Import ::= `import' ImportExpr {`,' ImportExpr} ImportExpr ::= StableId `.' (id | `_' | ImportSelectors) Import(expr, sels) ImportSelectors ::= `{' {ImportSelector `,'} (ImportSelector | `_') `}' ImportSelector ::= id [`=>' id | `=>' `_'] Ident(name), Pair(id, id) Dcl ::= `val' ValDcl | `var' VarDcl | `def' DefDcl | `type' {nl} TypeDcl | INT ValDcl ::= ids `:' Type PatDef(_, ids, tpe, EmptyTree) VarDcl ::= ids `:' Type PatDef(_, ids, tpe, EmptyTree) DefDcl ::= DefSig [`:' Type] DefDef(_, name, tparams, vparamss, tpe, EmptyTree) DefSig ::= id [DefTypeParamClause] DefParamClauses TypeDcl ::= id [TypTypeParamClause] ['=' Type] TypeDefTree(_, name, tparams, tpt) | id [HkTypeParamClause] TypeBounds TypeDefTree(_, name, tparams, bounds) Def ::= `val' PatDef | `var' VarDef | `def' DefDef | `type' {nl} TypeDcl | TmplDef | INT PatDef ::= Pattern2 {`,' Pattern2} [`:' Type] `=' Expr PatDef(_, pats, tpe?, expr) VarDef ::= PatDef | ids `:' Type `=' `_' DefDef ::= DefSig [`:' Type] `=' Expr DefDef(_, name, tparams, vparamss, tpe, expr) | DefSig [nl] `{' Block `}' DefDef(_, name, tparams, vparamss, tpe, Block) | `this' DefParamClause DefParamClauses DefDef(_, , Nil, vparamss, EmptyTree, expr | Block) (`=' ConstrExpr | [nl] ConstrBlock) TmplDef ::= ([`case'] `class' | `trait') ClassDef | [`case'] `object' ObjectDef ClassDef ::= id [ClsTypeParamClause] ClassDef(mods, name, tparams, templ) // [ConstrMods] ClsParamClauses TemplateOpt with DefDef(_, , Nil, vparamss, EmptyTree, EmptyTree) as first stat ConstrMods ::= AccessModifier | Annotation {Annotation} (AccessModifier | `this') ObjectDef ::= id TemplateOpt ModuleDef(mods, name, template) // no constructor TemplateOpt ::= [`extends' Template | [nl] TemplateBody] Template ::= ConstrApps [TemplateBody] | TemplateBody Template(constr, parents, self, stats) ConstrApps ::= ConstrApp {`with' ConstrApp} ConstrApp ::= AnnotType {ArgumentExprs} Apply(tp, args) ConstrExpr ::= SelfInvocation | ConstrBlock ConstrBlock ::= `{' SelfInvocation {semi BlockStat} `}' SelfInvocation ::= `this' ArgumentExprs {ArgumentExprs} TopStatSeq ::= TopStat {semi TopStat} TopStat ::= {Annotation [nl]} {Modifier} TmplDef | Import | Packaging | PackageObject | Packaging ::= `package' QualId [nl] `{' TopStatSeq `}' Package(qid, stats) PackageObject ::= `package' `object' ObjectDef object with package in mods. CompilationUnit ::= {`package' QualId semi} TopStatSeq Package(qid, stats) \end{lstlisting} }