1.1. Lexer
-
CoreCpp.Token[complete] -
CoreCpp.keywords[complete] -
CoreCpp.cppReserved[complete] -
CoreCpp.symbols3[complete] -
CoreCpp.symbols2[complete] -
CoreCpp.symbols1[complete] -
CoreCpp.Lexer.isIdentStart[complete] -
CoreCpp.Lexer.isIdentChar[complete]
Tokens fall in six classes, and the end token eof closes the array.
-
Reserved words, the 24 words
int,bool,void,if,else,while,for,return,true,false,auto,delete,new,nullptr,this,class,public,private,virtual,override,namespace,template,typenameandoperator. -
Type identifiers,
TypeId, with an uppercase initial. -
Variable identifiers,
VarId, with a lowercase initial or_, naming variables, fields, functions and methods. -
Namespace identifiers,
NsId, the identifiers of either case that::follows. -
Decimal integer literals,
IntLit. -
Operators and punctuation, with
[=]as a single token by the longest match rule.
There is no token >>, so Stack<Stack<int>> closes with two tokens >.
\begin{array}{lcl} \textit{Token} & ::= & \textit{Keyword}\ \mid\ \textit{TypeId}\ \mid\ \textit{VarId}\ \mid\ \textit{NsId}\ \mid\ \textit{IntLit}\ \mid\ \textit{Symbol} \\ \textit{Keyword} & ::= & \texttt{int}\ \mid\ \texttt{bool}\ \mid\ \texttt{void}\ \mid\ \texttt{class} \\ & \mid & \texttt{public}\ \mid\ \texttt{private}\ \mid\ \texttt{new}\ \mid\ \texttt{delete} \\ & \mid & \texttt{nullptr}\ \mid\ \texttt{this}\ \mid\ \texttt{virtual} \\ & \mid & \texttt{override}\ \mid\ \texttt{namespace}\ \mid\ \texttt{template} \\ & \mid & \texttt{typename}\ \mid\ \texttt{auto}\ \mid\ \texttt{if}\ \mid\ \texttt{else}\ \mid\ \texttt{while}\ \mid\ \texttt{for}\ \mid\ \texttt{return} \\ & \mid & \texttt{true}\ \mid\ \texttt{false}\ \mid\ \texttt{operator} \\ \textit{TypeId} & ::= & \textit{Upper}\ \textit{IdentChar}^{*} \\ \textit{VarId} & ::= & \big(\ \textit{Lower}\ \mid\ \texttt{\_}\ \big)\ \textit{IdentChar}^{*} \\ \textit{NsId} & ::= & \textit{TypeId}\ \mid\ \textit{VarId} \\ \textit{IntLit} & ::= & \textit{Digit}\ \textit{Digit}^{*} \\ \textit{Symbol} & ::= & \texttt{[=]} \\ & \mid & \texttt{==}\ \mid\ \texttt{!=}\ \mid\ \texttt{<=}\ \mid\ \texttt{>=}\ \mid\ \texttt{\&\&}\ \mid\ \texttt{||}\ \mid\ \texttt{->}\ \mid\ \texttt{::}\ \mid\ \texttt{--}\ \mid\ \texttt{++} \\ & \mid & \texttt{+}\ \mid\ \texttt{-}\ \mid\ \texttt{*}\ \mid\ \texttt{/}\ \mid\ \texttt{\%}\ \mid\ \texttt{<}\ \mid\ \texttt{>}\ \mid\ \texttt{!}\ \mid\ \texttt{?}\ \mid\ \texttt{:}\ \mid\ \texttt{=} \\ & \mid & \texttt{(}\ \mid\ \texttt{)}\ \mid\ \texttt{\{}\ \mid\ \texttt{\}}\ \mid\ \texttt{[}\ \mid\ \texttt{]}\ \mid\ \texttt{,}\ \mid\ \texttt{;}\ \mid\ \texttt{.}\ \mid\ \texttt{\&}\ \mid\ \texttt{\textasciitilde} \\ \textit{IdentChar} & ::= & \textit{Upper}\ \mid\ \textit{Lower}\ \mid\ \textit{Digit}\ \mid\ \texttt{\_} \\ \textit{Upper} & ::= & \texttt{A}\ \mid\ \ldots\ \mid\ \texttt{Z} \\ \textit{Lower} & ::= & \texttt{a}\ \mid\ \ldots\ \mid\ \texttt{z} \\ \textit{Digit} & ::= & \texttt{0}\ \mid\ \ldots\ \mid\ \texttt{9} \\ \textit{Skip} & ::= & \textit{WhiteSpace}\ \mid\ \texttt{//}\ \textit{NotNewline}^{*}\ \textit{Newline}^{?} \end{array}
The lexer covers the input by a sequence of Token and Skip, discards Skip, and takes the longest match at each position. A line comment ends at a newline or at the end of the input. The symbols of three characters are tried before those of two and of one.
Lean code for Definition1.1.1●8 definitions
Associated Lean declarations
-
CoreCpp.Token[complete]
-
CoreCpp.keywords[complete]
-
CoreCpp.cppReserved[complete]
-
CoreCpp.symbols3[complete]
-
CoreCpp.symbols2[complete]
-
CoreCpp.symbols1[complete]
-
CoreCpp.Lexer.isIdentStart[complete]
-
CoreCpp.Lexer.isIdentChar[complete]
-
CoreCpp.Token[complete] -
CoreCpp.keywords[complete] -
CoreCpp.cppReserved[complete] -
CoreCpp.symbols3[complete] -
CoreCpp.symbols2[complete] -
CoreCpp.symbols1[complete] -
CoreCpp.Lexer.isIdentStart[complete] -
CoreCpp.Lexer.isIdentChar[complete]
-
inductivedefined in CoreCpp/Token.leancomplete
inductive CoreCpp.Token : Type
inductive CoreCpp.Token : Type
Constructors
CoreCpp.Token.kw (s : String) : CoreCpp.Token
CoreCpp.Token.typeId (s : String) : CoreCpp.Token
CoreCpp.Token.varId (s : String) : CoreCpp.Token
CoreCpp.Token.nsId (s : String) : CoreCpp.Token
CoreCpp.Token.intLit (n : Nat) : CoreCpp.Token
CoreCpp.Token.sym (s : String) : CoreCpp.Token
CoreCpp.Token.eof : CoreCpp.Token
-
defdefined in CoreCpp/Token.leancomplete
def CoreCpp.keywords : List String
def CoreCpp.keywords : List String
Reserved words of the subset handled by this parser.
-
defdefined in CoreCpp/Token.leancomplete
def CoreCpp.cppReserved : List String
def CoreCpp.cppReserved : List String
The keywords of C++17 (N4659 §5.11 [lex.key], Table 5) and the alternative representations (Table 6). A Core C++ program uses none of them outside `keywords`, so every Core C++ program stays a C++ program.
-
defdefined in CoreCpp/Token.leancomplete
def CoreCpp.symbols3 : List String
def CoreCpp.symbols3 : List String
Symbols of three, two and one characters, longest first. The tokens `--` and `++` belong to no production. The lexer reads them so that `5--2` fails as it does in C++, where the longest match gives `--`.
-
defdefined in CoreCpp/Token.leancomplete
def CoreCpp.symbols2 : List String
def CoreCpp.symbols2 : List String
-
defdefined in CoreCpp/Token.leancomplete
def CoreCpp.symbols1 : List String
def CoreCpp.symbols1 : List String
-
defdefined in CoreCpp/Lexer.leancomplete
def CoreCpp.Lexer.isIdentStart (c : Char) : Bool
def CoreCpp.Lexer.isIdentStart (c : Char) : Bool
-
defdefined in CoreCpp/Lexer.leancomplete
def CoreCpp.Lexer.isIdentChar (c : Char) : Bool
def CoreCpp.Lexer.isIdentChar (c : Char) : Bool
-
CoreCpp.Lexer.identifier[complete] -
CoreCpp.Lexer.qualifiers[complete]
An identifier is classified by its initial after the reserved words are excluded. A further pass over the token array marks as an NsId every identifier whose next token is ::, of either case.
The pass qualifiers runs after the automaton, so it sees neither white space nor comments and marks std :: vector as it marks std::vector. The parser runs the automaton on each line of the Preproc output alone and the pass once on the tokens of all the lines, so a :: that starts a line marks the identifier that ends the line before.
That class is what lets a qualified name open a type where the case convention alone would read a variable, so std::vector<int> needs no reserved word.
Lean code for Definition1.1.2●2 definitions
Associated Lean declarations
-
CoreCpp.Lexer.identifier[complete]
-
CoreCpp.Lexer.qualifiers[complete]
-
CoreCpp.Lexer.identifier[complete] -
CoreCpp.Lexer.qualifiers[complete]
-
defdefined in CoreCpp/Lexer.leancomplete
def CoreCpp.Lexer.identifier (s : String) : CoreCpp.Token
def CoreCpp.Lexer.identifier (s : String) : CoreCpp.Token
Classifies an identifier as a reserved word, or else by its initial. An uppercase initial gives a type identifier, and a lowercase initial or `_` a variable identifier.
-
defdefined in CoreCpp/Lexer.leancomplete
def CoreCpp.Lexer.qualifiers (ts : Array CoreCpp.Token) : Array CoreCpp.Token
def CoreCpp.Lexer.qualifiers (ts : Array CoreCpp.Token) : Array CoreCpp.Token
Marks as a namespace identifier every identifier whose next token is `::`. The pass runs over the token array, so it sees neither the white space nor the comments the automaton has already dropped, and it marks `std :: vector` as it marks `std::vector`. `parseUnit` runs it once on the tokens of all the lines, so a `::` at the start of a line marks the identifier that ends the line before.
-
CoreCpp.lex[complete] -
CoreCpp.Lexer.run[complete] -
CoreCpp.Lexer.takeWhile[complete] -
CoreCpp.Lexer.matchSymbol[complete] -
CoreCpp.Lexer.skipLine[complete]
The function lex maps a string to an array of tokens ended by eof. It runs the automaton Lexer.run and then the pass of Definition 1.1.2. It discards white space and line comments, reads the longest run of digits as an integer literal, the longest run of identifier characters as an identifier, and tries the symbols of three, two and one characters in that order. Any other character is a lexical error.
The lexer also rejects what C++ would read otherwise, so that every Core C++ program is a C++ program with the same meaning.
-
It rejects a keyword of C++ or an alternative representation such as
andoutside the reserved words of the subset (N4659 §5.11, Tables 5 and 6). -
It rejects an integer literal with a leading
0, which C++ reads in octal, and one above 2147483647, to which C++ gives a type wider thanint. -
It reads
--and++as tokens that no production uses, so5--2fails as in C++, where the longest match gives--.
The automaton Lexer.run is partial, so Lean records an opaque constant that carries the type and not the body, and no property of it is proved here.
Lean code for Definition1.1.3●5 definitions
Associated Lean declarations
-
CoreCpp.lex[complete]
-
CoreCpp.Lexer.run[complete]
-
CoreCpp.Lexer.takeWhile[complete]
-
CoreCpp.Lexer.matchSymbol[complete]
-
CoreCpp.Lexer.skipLine[complete]
-
CoreCpp.lex[complete] -
CoreCpp.Lexer.run[complete] -
CoreCpp.Lexer.takeWhile[complete] -
CoreCpp.Lexer.matchSymbol[complete] -
CoreCpp.Lexer.skipLine[complete]
-
defdefined in CoreCpp/Lexer.leancomplete
def CoreCpp.lex (input : String) : Except String (Array CoreCpp.Token)
def CoreCpp.lex (input : String) : Except String (Array CoreCpp.Token)
The lexer, the automaton `Lexer.run` followed by the pass `Lexer.qualifiers`.
-
opaquedefined in CoreCpp/Lexer.leancomplete
opaque CoreCpp.Lexer.run (cs : List Char) (acc : Array CoreCpp.Token) : Except String (Array CoreCpp.Token)
opaque CoreCpp.Lexer.run (cs : List Char) (acc : Array CoreCpp.Token) : Except String (Array CoreCpp.Token)
The automaton. It discards white space and line comments, reads the longest run of digits as an integer literal and the longest run of identifier characters as an identifier, tries the symbols of three, two and one characters in that order, and ends the array with `eof`.
-
defdefined in CoreCpp/Lexer.leancomplete
def CoreCpp.Lexer.takeWhile (p : Char → Bool) : List Char → String × List Char
def CoreCpp.Lexer.takeWhile (p : Char → Bool) : List Char → String × List Char
Takes the longest prefix of characters satisfying `p`.
-
defdefined in CoreCpp/Lexer.leancomplete
def CoreCpp.Lexer.matchSymbol (syms : List String) (cs : List Char) : Option (String × List Char)
def CoreCpp.Lexer.matchSymbol (syms : List String) (cs : List Char) : Option (String × List Char)
Tries to match one of the symbols at the start of the input.
-
defdefined in CoreCpp/Lexer.leancomplete
def CoreCpp.Lexer.skipLine : List Char → List Char
def CoreCpp.Lexer.skipLine : List Char → List Char
Discards a line comment, up to the next newline or the end of the input.