Lexical Analysis with ANTLRA lexer (often called a scanner) breaks up an input stream of characters into vocabulary symbols for a parser, which applies a grammatical structure to that symbol stream. Because ANTLR employs the same recognition mechanism for lexing, parsing, and tree parsing, ANTLR-generated lexers are much stronger than DFA-based lexers such as those generated by DLG (from PCCTS 1.33) and lex. The increase in lexing power comes at the cost of some inconvenience in lexer specification and indeed requires a serious shift your thoughts about lexical analysis. See a comparison of LL(k) and DFA-based lexical analysis. ANTLR generates predicated-LL(k) lexers, which means that you can have semantic and syntactic predicates and use k>1 lookahead. The other advantages are:
The overall structure of a lexer is: class MyLexer extends Lexer; options { some options } { lexer class members } lexical rules Lexical RulesRules defined within a lexer grammar must have a name beginning with an uppercase letter. These rules implicitly match characters on the input stream instead of tokens on the token stream. Referenced grammar elements include token references (implicit lexer rule references), characters, and strings. Lexer rules are processed in the exact same manner as parser rules and, hence, may specify arguments and return values; further, lexer rules can also have local variables and use recursion. The following rule defines a rule called ID that is available as a token type in the parser. ID : ( 'a'..'z' )+ ; This rule would become part of the resulting lexer and would appear as a method called mID(). Lexer rules allow your parser to match context-free structures on the input character stream as opposed to the much weaker regular structures (using a DFA--deterministic finite automaton). For example, consider that matching nested curly braces with a DFA must be done using a counter whereas nested curlies are trivially matched with a context-free grammar: ACTION : '{' ( ACTION | ~'}' )* '}' ; The recursion, of course, is the dead giveaway that this is not an ordinary lexer rule. Because the same algorithms are used to analyze lexer and parser rules, lexer rules may use more than a single symbol of lookahead, can use semantic predicates, and can specify syntactic predicates to look arbitrarily ahead, thus, providing recognition capabilities beyond the LL(k) languages into the context-sensitive. Here is a simple example that requires k>1 lookahead: ESCAPE_CHAR : '\\' 't' // two char of lookahead needed, | '\\' 'n' // due to common left-prefix ; To illustrate the use of syntactic predicates for lexer rules, consider the problem of distinguishing between floating point numbers and ranges in Pascal. Input 3..4 must be broken up into 3 tokens: INT, RANGE, followed by INT. Input 3.4, on the other hand, must be sent to the parser as a REAL. The trouble is that the series of digits before the first '.' can be arbitrarily long. The scanner then must consume the first '.' to see if the next character is a '.', which would imply that it must back up and consider the first series of digits an integer. Using a non-backtracking lexer makes this task essentially impossible. However, a syntactic predicate can be used to specify what arbitrary lookahead is necessary: class Pascal; prog: INT ( RANGE INT { System.out.println("INT .. INT"); } | EOF { System.out.println("plain old INT"); } ) | REAL { System.out.println("token REAL"); } ; lexclass LexPascal; WS : (' ' | '\t' | '\n' | '\r') { $setType(Token.SKIP); } ; protected INT : ('0'..'9')+ ; protected REAL: INT '.' INT ; RANGE : ".." ; RANGE_OR_INT : ( INT ".." ) => INT { $setType(INT); } | ( INT '.' ) => REAL { $setType(REAL); } | INT { $setType(INT); } ; ANTLR lexer rules are even able to handle FORTRAN assignments and other difficult lexical constructs. Consider the following DO loop: DO 100 I = 1,10 If the comma were replaced with a period, the loop would become an assignment to a weird variable called "DO100I": DO 100 I = 1.10 The following rules correctly differentiate the two cases: DO_OR_VAR : (DO_HEADER)=> "DO" { $setType(DO); } | VARIABLE { $setType(VARIABLE); } ; protected DO_HEADER options { ignore=WS; } : "DO" INT VARIABLE '=' EXPR ',' ; protected INT : ('0'..'9')+; protected WS : ' '; protected VARIABLE : 'A'..'Z' ('A'..'Z' | ' ' | '0'..'9')* { /* strip space from end */ } ; // just an int or float protected EXPR : INT ( '.' (INT)? )? ; Return valuesAll rules return a token object (conceptually) automatically, which contains the text matched for the rule and its token type at least. To specify a user-defined return value, define a return value and set it in an action: protected INT returns [int v] : (0..9)+ { v=Integer.valueOf($getText); } ; Non-protected rules cannot have a return type as the parser cannot access the return value leading to confusion. Skipping charactersTo have the characters matched by a rule ignored, set the token type to Token.SKIP. For example, WS : ( ' ' | '\t' | '\n' { newline(); } | '\r' )+ { $setType(Token.SKIP); } ; Distinguishing between lexer rulesANTLR generates a rule called nextToken which has an alternative containing a lexer rule reference, one alternative for each non-protected lexer rule. The first few characters of the token are used to route the lexer to the appropriate lexical rule. The alternatives of nextToken are analyzed for determinism; i.e., with k characters of lookahead can the lexer determine which lexer rule to attempt. The ANTLR input: INT : ('0'..'9')+; WS : ' ' | '\t' | '\r' | '\n'; produces a switch statement in nextToken: switch (LA(1)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': mINT(); break; case '\t': case '\n': case '\r': case ' ': mWS(); break; default: // error } Definition order and lexical ambiguitiesANTLR 2.0 does not follow the common lexer rule of "first definition wins" (the alternatives within a rule, however, still follow this rule). Instead, sufficient power is given to handle the two most common cases of ambiguity, namely "keywords vs. identifiers", and "common prefixes"; and for especially nasty cases you can use syntactic predicates. Keywords and literalsMany languages have a general "identifier" lexical rule, and keywords that are special cases of the identifier pattern. A typical identifier token is defined as: ID : LETTER (LETTER | DIGIT)*; This is often in conflict with keywords. ANTLR 2.0 solves this problem by letting you put fixed keywords into a literals table. The literals table (which is usally implemented as a hash table in the lexer) is checked after each token is matched, so that the literals effectively override the more general identifier pattern. Literals are created in one of two ways. First, any double-quoted string used in a parser is automatically entered into the literals table of the associated lexer. Second, literals may be specified in the lexer grammar by means of the literal option. In addition, the testLiterals option gives you fine-grained control over the generation of literal-testing code. Common prefixesFixed-length common prefixes in lexer rules are best handled by increasing the lookahead depth of the lexer. For example, some operators from Java: class MyLexer extends Lexer; options { k=4; } GT : ">"; GE : ">="; RSHIFT : ">>"; RSHIFT_ASSIGN : ">>="; UNSIGNED_RSHIFT : ">>>"; UNSIGNED_RSHIFT_ASSIGN : ">>>="; Token definition filesToken definitions can be transferred from one grammar to another by way of token definition files. This is accomplished using the importVocab and exportVocab options. Character classesUse the ~ operator to invert a character or set of characters. For example, to match any character other than newline, the following rule references ~'\n'. SL_COMMENT: "//" (~'\n')* '\n'; The ~ operator also inverts a character set: NOT_WS: ~(' ' | '\t' | '\n' | '\r'); The range operator can be used to create sequential character sets: DIGIT : '0'..'9' ; Token AttributesSee the next section. Lexical lookahead and the end-of-token symbolA unique situation occurs when analyzing lexical grammars, one which is similar to the end-of-file condition when analyzing regular grammars. Consider how you would compute lookahead sets for the ('b' | ) subrule in following rule B: class L extends Lexer; A : B 'b' ; protected // only called from another lex rule B : 'x' ('b' | ) ; The lookahead for the first alternative of the subrule is clearly 'b'. The second alternative is empty and the lookahead set is the set of all characters that can follow references to the subrule, which is the follow set for rule B. In this case, the 'b' character follows the reference to B and is therefore the lookahead set for the empty alt indirectly. Because 'b' begins both alternatives, the parsing decision for the subrule is nondeterminism or ambiguous as we sometimes say. ANTLR will justly generate a warning for this subrule (unless you use the warnWhenFollowAmbig option). Now, consider what would make sense for the lookahead if rule A did not exist and rule B was not protected (it was a complete token rather than a "subtoken"): B : 'x' ('b' | ) ; In this case, the empty alternative finds only the end of the rule as the lookahead with no other rules referencing it. In the worst case, any character could follow this rule (i.e., start the next token or error sequence). So, should not the lookahead for the empty alternative be the entire character vocabulary? And should not this result in a nondeterminism warning as it must conflict with the 'b' alternative? Conceptually, yes to both questions. From a practical standpoint, however, you are clearly saying "heh, match a 'b' on the end of token B if you find one." I argue that no warning should be generated and ANTLR's policy of matching elements as soon as possible makes sense here as well. Another reason not to represent the lookahead as the entire vocabulary is that a vocabulary of '\u0000'..'\uFFFF' is really big (one set is 2^16 / 32 long words of memory!). Any alternative with '<end-of-token>' in its lookahead set will be pushed to the ELSE or DEFAULT clause by the code generator so that huge bitsets can be avoided. The summary is that lookahead purely derived from hitting the end of a lexical rule (unreferenced by other rules) cannot be the cause of a nondeterminism. The following table summarizes a bunch of cases that will help you figure out when ANTLR will complain and when it will not.
You might be wondering why the first subrule below is ambiguous: ('a')? ('a')? The answer is that the NFA to DFA conversion would result in a DFA with the 'a' transitions merged into a single state transition! This is ok for a DFA where you cannot have actions anywhere except after a complete match. Remember that ANTLR lets you do the following: ('a' {do-this})? ('a' {do-that})? One other thing is important to know. Recall that alternatives in lexical rules are reordered according to their lookahead requirements, from highest to lowest. A : 'a' | 'a' 'b' ; At k=2, ANTLR can see 'a' followed by '<end-of-token>' for the first alternative and 'a' followed by 'b' in the second. The lookahead at depth 2 for the first alternative being '<end-of-token>' suppressing a warning that depth two can match any character for the first alternative. To behave naturally and to generate good code when no warning is generated, ANTLR reorders the alternatives so that the code generated is similar to: A() { if ( LA(1)=='a' && LA(2)=='b' ) { // alt 2 match('a'); match('b'); } else if ( LA(1)=='a' ) { // alt 1 match('a') } else {error;} } Note the lack of lookahead test for depth 2 for alternative 1. When an empty alternative is present, ANTLR moves it to the end. For example, A : 'a' | | 'a' 'b' ; results in code like this: A() { if ( LA(1)=='a' && LA(2)=='b' ) { // alt 2 match('a'); match('b'); } else if ( LA(1)=='a' ) { // alt 1 match('a') } else { } } Note that there is no way for a lexing error to occur here (which makes sense because the rule is optional--though this rule only makes sense when protected). Semantic predicates get moved along with their associated alternatives when the alternatives are sorted by lookahead depth. It would be weird if the addition of a {true}? predicate (which implicitly exists for each alternative) changed what the lexer recognized! The following rule is reorder so that alternative 2 is tested for first. B : {true}? 'a' | 'a' 'b' ; Syntactic predicates are not reordered. Mentioning the predicate after the rule it conflicts with results in an ambiguity such as is in this rule: F : 'c' | ('c')=> 'c' ; Other alternatives are, however, reordered with respect to the syntactic predicates even when a switch is generated for the LL(1) components and the syntactic predicates are pushed the default case. The following rule illustrates the point. F : 'b' | {/* empty-path */} | ('c')=> 'c' | 'c' | 'd' | 'e' ; Rule F's decision is generated as follows: switch ( la_1) { case 'b': { match('b'); break; } case 'd': { match('d'); break; } case 'e': { match('e'); break; } default: boolean synPredMatched15 = false; if (((la_1=='c'))) { int _m15 = mark(); synPredMatched15 = true; guessing++; try { match('c'); } catch (RecognitionException pe) { synPredMatched15 = false; } rewind(_m15); guessing--; } if ( synPredMatched15 ) { match('c'); } else if ((la_1=='c')) { match('c'); } else { if ( guessing==0 ) { /* empty-path */ } } } Notice how the empty path got moved after the test for the 'c' alternative. Scanning Binary Files[Prior to 2.2.3, ANTLR was unable to parse binary files.] Character literals are not limited to printable ASCII characters. To demonstrate the concept, imagine that you want to parse a binary file that contains strings and short integers. To distinguish between them, marker bytes are used according to the following format:
Sample input (274 followed by "a test") might look like the following in hex (output from UNIX od -h command):<PHONE_NUMBER> 00 01 12 01 61 20 74 65 73 74 02 or as viewed as characters:<PHONE_NUMBER> \0 001 022 001 a t e s t 002 The parser is trivially just a (...)+ around the two types of input tokens: class DataParser extends Parser; file: ( sh:SHORT {System.out.println(sh.getText());} | st:STRING {System.out.println("\""+ st.getText()+"\"");} )+ ; All of the interesting stuff happens in the lexer. First, define the class and set the vocabulary to be all 8 bit binary values: class DataLexer extends Lexer; options { charVocabulary = '\u0000'..'\u00FF'; } Then, define the two tokens according to the specifications, with markers around the string and a single marker byte in front of the short: SHORT : // match the marker followed by any 2 bytes '\0' high:. lo:. { // pack the bytes into a two-byte short int v = (((int)high)<<8) + lo; // make a string out of the value $setText(""+v); } ; STRING : '\1'! // begin string (discard) ( ~'\2' )* '\2'! // end string (discard) ; To invoke the parser, use something like the following: import java.io.*; class Main { public static void main(String[] args) { try { // use DataInputStream to grab bytes DataLexer lexer = new DataLexer( new DataInputStream(System.in) ); DataParser parser = new DataParser(lexer); parser.file(); } catch(Exception e) { System.err.println("exception: "+e); } } } Scanning Unicode CharactersANTLR (as of 2.7.1) allows you to recognize input composed of Unicode characters; that is, you are not restricted to 8 bit ASCII characters. I would like to emphasize that ANTLR allows, but does yet not support Unicode as there is more work to be done. For example, end-of-file is currently incorrectly specified: CharScanner.EOF_CHAR=(char)-1; This must be an integer -1 not char, which is actually narrowed to 0xFFFF via the cast. I have to go throught the entire code base looking for these problems. Plus, we should really have a special syntax to mean "java identifier character" and some standard encodings for non-Western character sets etc... Another problem is that ANTLR generates bit sets when a few range checks would work. This makes for some big output files (all data), but at least the Java compilers will compile the output now (previously giant switch expressions would prevent compilation). The following is a very simple example of how to match a series of space-separated identifiers. class L extends Lexer; options { // Allow any char but \uFFFF (16 bit -1) charVocabulary='\u0000'..'\uFFFE'; } { private static boolean done = false; public void uponEOF() throws TokenStreamException, CharStreamException { done=true; } public static void main(String[] args) throws Exception { L lexer = new L(System.in); while ( !done ) { Token t = lexer.nextToken(); System.out.println("Token: "+t); } } } ID : ID_START_LETTER ( ID_LETTER )* ; WS : (' '|'\n') {$setType(Token.SKIP);} ; protected ID_START_LETTER : '$' | '_' | 'a'..'z' | '\u0080'..'\ufffe' ; protected ID_LETTER : ID_START_LETTER | '0'..'9' ; A final note on Unicode. The ~x "not" operator includes everything in your specified vocabulary (up to 16 bit character space) except x. For example, ~('$'|'a'..'z') results in every unicode character except '$' and lowercase latin-1 letters, assuming your charVocabulary is 0..FFFF. Manipulating Token Text and ObjectsOnce you have specified what to match in a lexical rule, you may ask "what can I discover about what will be matched for each rule element?" ANTLR allows you to label the various elements and, at parse-time, access the text matched for the element. You can even specify the token object to return from the rule and, hence, from the lexer to the parser. This section describes the text and token object handling characteristics of ANTLR. Manipulating the Text of a Lexical RuleThere are times when you want to look at the text matched for the current rule, alter it, or set the text of a rule to a new string. The most common case is when you want to simply discard the text associated with a few of the elements that are matched for a rule such as quotes. ANTLR provides the '!' operator that lets you indicate certain elements should not contribute to the text for a token being recognized. The '!' operator is used just like when building trees in the parser. For example, if you are matching the HTML tags and you do not want the '<' and '>' characters returned as part of the token text, you could manually remove them from the token's text before they are returned, but a better way is to suffix the unwanted characters with '!'. For example, the <br> tag might be recognized as follows: BR : '<'! "br" '>'! ; // discard < and > Suffixing a lexical rule reference with '!' forces the text matched by the invoked rule to be discarded (it will not appear in the text for the invoking rule). For example, if you do not care about the mantissa of a floating point number, you can suffix the rule that matches it with a '!': FLOAT : INT ('.'! INT!)? ; // keep only first INT As a shorthand notation, you may suffix an alternative or rule with '!' to indicate the alternative or rule should not pass any text back to the invoking rule or parser (if nonprotected): // ! on rule: nothing is auto added to text of rule. rule! : ... ; // ! on alt: nothing is auto added to text for alt rule : ... |! ...;
While the '!' implies that the text is not added to the text for the current rule, you can label an element to access the text (via the token if the element is a rule reference). In terms of implementation, the characters are always added to the current text buffer, but are carved out when necessary (as this will be the exception rather than the rule, making the normal case efficient). The '!' operator is great for discarding certain characters or groups of characters, but what about the case where you want to insert characters or totally reset the text for a rule or token? ANTLR provides a series of special methods to do this (we prefix the methods with '$' because Java does not have a macro facility and ANTLR must recognize the special methods in your actions). The following table summarizes.
One of the great things about an ANTLR generated lexer is that the text of a token can be modified incrementally as the token is recognized (an impossible task for a DFA-based lexer): STRING: '"' ( ESCAPE | ~('"'|'\\') )* '"' ; protected ESCAPE : '\\' ( 'n' { $setText("\n"); } | 'r' { $setText("\r"); } | 't' { $setText("\t"); } | '"' { $setText("\""); } ) ; Token Object CreationBecause lexical rules can call other rules just like in the parser, you sometimes want to know what text was matched for that portion of the token being matched. To support this, ANTLR allows you to label lexical rules and obtain a Token object representing the text, token type, line number, etc... matched for that rule reference. This ability corresponds to be able to access the text matched for a lexical state in a DFA-based lexer. For example, here is a simple rule that prints out the text matched for a rule reference, INT. INDEX : '[' i:INT ']' {System.out.println(i.getText());} ; INT : ('0'..'9')+ ; If you moved the labeled reference and action to a parser, it would the same thing (match an integer and print it out). All lexical rules conceptually return a Token object, but in practice this would be inefficient. ANTLR generates methods so that a token object is created only if any invoking reference is labeled (indicating they want the token object). Imagine another rule that calls INT without a label. FLOAT : INT ('.' INT)? ;In this case, no token object is created for either reference to INT. You will notice a boolean argument to every lexical rule that tells it whether or not a token object should be created and returned (via a member variable). All nonprotected rules (those that are "exposed" to the parser) must always generate tokens, which are passed back to the parser. Heterogeneous Token Object StreamsWhile token creation is normally handled automatically, you can also manually specify the token object to be returned from a lexical rule. The advantage is that you can pass heterogeneous token objects back to the parser, which is extremely useful for parsing languagues with complicated tokens such as HTML (the <img> and <table> tokens, for example, can have lots of attributes). Here is a rule for the <img> tag that returns a token object of type ImageToken: IMAGE { Attributes attrs; } : "<img " attrs=ATTRIBUTES '>' { ImageToken t = new ImageToken(IMAGE,$getText); t.setAttributes(attrs); $setToken(t); } ; ATTRIBUTES returns [Attributes a] : ... ; The $setToken function specifies that its argument is to be returned when the rule exits. The parser will receive this specific object instead of a CommonToken or whatever else you may have specified with the Lexer.setTokenObjectClass method. The action in rule IMAGE references a token type, IMAGE, and a lexical rule references, ATTRIBUTES, which matches all of the attributes of an image tag and returns them in a data structure called Attributes. What would it mean for rule IMAGE to be protected (i.e., referenced only from other lexical rules rather than from nextToken)? Any invoking labeled rule reference would receive the object (not the parser) and could examine it, or manipulate it, or pass it on to the invoker of that rule. For example, if IMAGE were called from TAGS rather than being nonprotected, rule TAGS would have to pass the token object back to the parser for it. TAGS : IMG:IMAGE {$setToken(img);} // pass to parser | PARAGRAPH // probably has no special token | ... ; Setting the token object for a nonprotected rule invoked without a label has no effect other than to waste time creating an object that will not be used. We use a CharScanner member _returnToken to do the return in order to not conflict with return values used by the grammar developer. For example, PTAG: "<p>" {$setToken(new ParagraphToken($$));} ; which would be translated to something like: protected final void mPTAG() throws RecognitionException, CharStreamException, TokenStreamException { Token _token = null; match("<p>"); _returnToken = new ParagraphToken(text-of-current-rule); } Filtering Input StreamsYou often want to perform an action upon seeing a pattern or two in a complicated input stream, such as pulling out links in an HTML file. One solution is to take the HTML grammar and just put actions where you want. Using a complete grammar is overkill and you may not have a complete grammar to start with. ANTLR provides a mechanism similar to AWK that lets you say "here are the patterns I'm interested in--ignore everything else." Naturally, AWK is limited to regular expressions whereas ANTLR accepts context-free grammars (Uber-AWK?). For example, consider pulling out the <p> and <br> tags from an arbitrary HTML file. Using the filter option, this is easy: class T extends Lexer; options { k=2; filter=true; } P : "<p>" ; BR: "<br>" ; In this "mode", there is no possibility of a syntax error. Either the pattern is matched exactly or it is filtered out. This works very well for many cases, but is not sophisticated enough to handle the situation where you want "almost matches" to be reported as errors. Consider the addition of the <table...> tag to the previous grammar: class T extends Lexer; options { k=2; filter = true; } P : "<p>" ; BR: "<br>" ; TABLE : "<table" (WS)? (ATTRIBUTE)* (WS)? '>' ; WS : ' ' | '\t' | '\n' ; ATTRIBUTE : ... ; Now, consider input "<table 8 = width ;>" (a bogus table definition). As is, the lexer would simply scarf past this input without "noticing" the invalid table. What if you want to indicate that a bad table definition was found as opposed to ignoring it? Call method setCommitToPath(boolean commit) in your TABLE rule to indicate that you want the lexer to commit to recognizing the table tag: TABLE : "<table" (WS)? {setCommitToPath(true);} (ATTRIBUTE)* (WS)? '>' ; Input "<table 8 = width ;>" would result in a syntax error. Note the placement after the whitespace recognition; you do not want <tabletop> reported as a bad table (you want to ignore it). One further complication in filtering: What if the "skip language" (the stuff in between valid tokens or tokens of interest) cannot be correctly handled by simply consuming a character and trying again for a valid token? You may want to ignore comments or strings or whatever. In that case, you can specify a rule that scarfs anything between tokens of interest by using option filter=RULE. For example, the grammar below filters for <p> and <br> tags as before, but also prints out any other tag (<...>) encountered. class T extends Lexer; options { k=2; filter=IGNORE; charVocabulary = '\3'..'\177'; } P : "<p>" ; BR: "<br>" ; protected IGNORE : '<' (~'>')* '>' {System.out.println("bad tag:"+$getText);} | ( "\r\n" | '\r' | '\n' ) {newline();} | . ; Notice that the filter rule must track newlines in the general case where the lexer might emit error messages so that the line number is not stuck at 0. The filter rule is invoked either when the lookahead (in nextToken) predicts none of the nonprotected lexical rules or when one of those rules fails. In the latter case, the input is rolled back before attempting the filter rule. Option filter=true is like having a filter rule such as: IGNORE : . ; Actions in regular lexical rules are executed even if the rule fails and the filter rule is called. To do otherwise would require every valid token to be matched twice (once to match and once to do the actions like a syntactic predicate)! Plus, there are few actions in lexer rules (usually they are at the end at which point an error cannot occur). Is the filter rule called when commit-to-path is true and an error is found in a lexer rule? No, an error is reported as with filter=true. What happens if there is a syntax error in the filter rule? Well, you can either put an exception handler on the filter rule or accept the default behavior, which is to consume a character and begin looking for another valid token. In summary, the filter option allows you to:
ANTLR Masquerading as SEDTo make ANTLR generate lexers that behave like the UNIX utility sed (copy standard in to standard out except as specified by the replace patterns), use a filter rule that does the input to output copying: class T extends Lexer; options { k=2; filter=IGNORE; charVocabulary = '\3'..'\177'; }P : "<p>" {System.out.print("<P>");}; BR : "<br>" {System.out.print("<BR>");}; protected IGNORE : ( "\r\n" | '\r' | '\n' ) {newline(); System.out.println("");} | c:. {System.out.print(c);} ; This example dumps anything other than <p> and <br> tags to standard out and pushes lowercase <p> and <br> to uppercase. Works great. Nongreedy SubrulesQuick: What does the following match? BLOCK : '{' (.)* '}'; Your first reaction is that it matches any set of characters inside of curly quotes. In reality, it matches '{' followed by every single character left on the input stream! Why? Well, because ANTLR loops are greedy--they consume as much input as they can match. Since the wildcard matches any character, it consumes the '}' and beyond. This is a pain for matching strings, comments and so on. Why can't we switch it around so that it consumes only until it sees something on the input stream that matches what follows the loop, such as the '}'? That is, why can't we make loops nongreedy? The answer is we can, but sometimes you want greedy and sometimes you want nongreedy (PERL has both kinds of closure loops now too). Unfortunately, parsers usually want greedy and lexers usually want nongreedy loops. Rather than make the same syntax behave differently in the various situations, Terence decided to leave the semantics of loops as they are (greedy) and make a subrule option to make loops nongreedy. Greedy SubrulesI have yet to see a case when building a parser grammar where I did not want a subrule to match as much input as possible. For example, the solution to the classic if-then-else clause ambiguity is to match the "else" as soon as possible: stat : "if" expr "then" stat ("else" stat)? | ... ; This ambiguity (which statement should the "else" be attached to) results in a parser nondeterminism. ANTLR warns you about the (...)? subrule as follows: warning: line 3: nondeterminism upon k==1:"else" between alts 1 and 2 of block If, on the other hand, you make it clear to ANTLR that you want the subrule to match greedily (i.e., assume the default behavior), ANTLR will not generate the warning. Use the greedy subrule option to tell ANTLR what you want: stat : "if" expr "then" stat ( options {greedy=true;} : "else" stat)? | ID ; You are not altering the behavior really, since ANTLR was going to choose to match the "else" anyway, but you have avoided a warning message. There is no such thing as a nongreedy (...)? subrule because telling an optional subrule not to match anything is the same as not specifying the subrule in the first place. If you make the subrule nongreedy, you will see: warning in greedy.g: line(4), Being nongreedy only makes sense for (...)+ and (...)* warning: line 4: nondeterminism upon k==1:"else" between alts 1 and 2 of block Greedy subrules are very useful in the lexer also. If you want to grab any whitespace on the end of a token definition, you can try (WS)? for some whitespace rule WS: ID : ('a'..'z')+ (WS)? ; However, if you want to match ID in a loop in another rule that could also match whitespace, you will run into a nondeterminism warning. Here is a contrived loop that conflicts with the (WS)? in ID: LOOP : ( ID | WS )+ ; The whitespace on the end of the ID could be matched in ID or in LOOP now. ANTLR chooses to match the WS immediately, in ID. To shut off the warning, simply tell ANTLR that you mean for it do be greedy, it's default behavior: ID : ('a'..'z')+ (options {greedy=true;}:WS)? ; Nongreedy Lexer SubrulesANTLR's default behavior of matching as much as possible in loops and optional subrules is sometimes not what you want in lexer grammars. Most loops that match "a bunch of characters" in between markers, like curly braces or quotes, should be nongreedy loops. For example, to match a nonnested block of characters between curly braces, you want to say: CURLY_BLOCK_SCARF : '{' (.)* '}' ; Unfortunately, this does not work--it will consume everything after the '{' until the end of the input. The wildcard matches anything including '}' and so the loop merrily consumes past the ending curly brace. To force ANTLR to break out of the loop when it sees a lookahead sequence consistent with what follows the loop, use the greedy subrule option: CURLY_BLOCK_SCARF : '{' ( options { greedy=false; } : . )* '}' ; To properly take care of newlines inside the block, you should really use the following version that "traps" newlines and bumps up the line counter: CURLY_BLOCK_SCARF : '{' ( options { greedy=false; } : '\r' ('\n')? {newline();} | '\n' {newline();} | . )* '}' ; Limitations of Nongreedy SubrulesWhat happens when what follows a nongreedy subrule is not as simple as a single "marker" character like a right curly brace (i.e., what about when you need k>1 to break out of a loop)? ANTLR will either "do the right thing" or warn you that it might not. First, consider the matching C comments: CMT : "/*" (.)* "*/" ; As with the curly brace matching, this rule will not stop at the end marker because the wildcard matches the "*/" end marker as well. You must tell ANTLR to make the loop nongreedy: CMT : "/*" (options {greedy=false;} :.)* "*/" ; You will not get an error and ANTLR will generate an exit branch do { // nongreedy exit test if ((LA(1)=='*')) break _loop3; ... Ooops. k=1, which is not enough lookahead. ANTLR did not generate a warning because it assumes you are providing enough lookahead for all nongreedy subrules. ANTLR cannot determine how much lookahead to use or how much is enough because, by definition, the decision is ambiguous--it simply generates a decision using the maximum lookahead. You must provide enough lookahead to let ANTLR see the full end marker: class L extends Lexer; options { k=2; } CMT : "/*" (options {greedy=false;} :.)* "*/" ; Now, ANTLR will generate an exit branch using k=2. do { // nongreedy exit test if ((LA(1)=='*') && (LA(2)=='/')) break _loop3; ... If you increase k to 3, ANTLR will generate an exit branch using k=3 instead of 2, even though 2 is sufficient. We know that k=2 is ok, but ANTLR is faced with a nondeterminism at it will use as much information as it has to yield a deterministic parser. There is one more issue that you should be aware of. Because ANTLR generates linear approximate decisions instead of full LL(k) decisions, complicated "end markers" can confuse ANTLR. Fortunately, ANTLR knows when it is confused and will let you know. Consider a simple contrived example where a loop matches either ab or cd: R : ( options {greedy=false;} : ("ab"|"cd") )+ ("ad"|"cb") ; Following the loop, the grammar can match ad or cb. These exact sequences are not a problem for a full LL(k) decision, but due to the extreme compression of the linear approximate decision, ANTLR will generate an inaccurate exit branch. In other words, the loop will exit, for example, on ab even though that sequence cannot be matched following the loop. The exit condition is as follows: // nongreedy exit test if ( _cnt10>=1 && (LA(1)=='a'||LA(1)=='c') && (LA(2)=='b'||LA(2)=='d')) break _loop10; where the _cnt10 term ensures the loop goes around at least once (but has nothing to do with the nongreedy exit branch condition really). Note that ANTLR has compressed all characters that can possibly be matched at a lookahead depth into a single set, thus, destroying the sequence information. The decision matches the cross product of the sets, including the spurious lookahead sequences such as ab. Fortunately, ANTLR knows when a decision falls between its approximate decision and a full LL(k) decision--it warns you as follows: warning in greedy.g: line(3), nongreedy block may exit incorrectly due to limitations of linear approximate lookahead (first k-1 sets in lookahead not singleton). The parenthetical remark gives you a hint that some k>1 lookahead sequences are correctly predictable even with the linear approximate lookahead compression. The idea is that if all sets for depths 1..(k-1) are singleton sets (exactly one lookahead sequence for first k-1 characters) then linear approximate lookahead compression does not weaken your parser. So, the following variant does not yield a warning since the exit branch is linear approximate as well as full LL(k): R : ( options {greedy=false;} : . )+ ("ad"|"ae") ; The exit branch decision now tests lookahead as follows: (LA(1)=='a') && (LA(2)=='d'||LA(2)=='e') which accurately predicts when to exit. Lexical StatesANTLR has the ability to switch between multiple lexers using a token stream multiplexor. Please see the discussion in streams. The End Of File ConditionA method is available for reacting to the end of file condition as if it were an event; e.g., you might want to pop the lexer state at the end of an include file. This method, CharScanner.uponEOF(), is called from nextToken() right before the scanner returns an EOF_TYPE token object to parser: public void uponEOF()| throws TokenStreamException, CharStreamException; This event is not generated during a syntactic predicate evaluation (i.e., when the parser is guessing) nor in the middle of the recognition of a lexical rule (that would be an IO exception). This event is generated only after the complete evaluation of the last token and upon the next request from the parser for a token. You can throw exceptions from this method like "Heh, premature eof" or a retry stream exception. See the includeFile/P.g for an example usage. Case sensitivityYou may use option caseSensitive=false in the lexer to indicate that you do not want case to be significant when matching characters against the input stream. For example, you want element 'd' to match either upper or lowercase D, however, you do not want to change the case of the input stream. We have implemented this feature by having the lexer's LA() lookahead method return lowercase versions of the characters. Method consume() still adds the original characters to the string buffer associated with a token. We make the following notes:
Case sensitivity for literals is handled separately. That is, set lexer option caseSensitiveLiterals to false when you want the literals testing to be case-insensitive. Implementing this required changes to the literals table. Instead of adding a String, it adds an ANTLRHashString that implements a case-insensitive or case-sensitive hashing as desired. Note: ANTLR checks the characters of a lexer string to make sure they are lowercase, but does not process escapes correctly--put that one on the "to do" list. Ignoring whitespace in the lexerOne of the great things about ANTLR is that it generates full predicated-LL(k) lexers rather than the weaker (albeit sometimes easier-to-specify) DFA-based lexers of DLG. With such power, you are tempted (and encouraged) to do real parsing in the lexer. A great example of this is HTML parsing, which begs for a two-level parse: the lexer parsers all the attributes and so on within a tag, but the parser does overall document structure and ordering of the tags etc... The problem with parsing within a lexer is that you encounter the usual "ignore whitespace" issue as you do with regular parsing. For example, consider matching the <table> tag of HTML, which has many attributes that can be specified within the tag. A first attempt might yield: OTABLE : "<table" (ATTR)* '>' ; Unfortunately, input "<table border=1>" does not parse because of the blank character after the table identifier. The solution is not to simply have the lexer ignore whitespace as it is read in because the lookahead computations must see the whitespace characters that will be found in the input stream. Further, defining whitespace as a rudimentary set of things to ignore does not handle all cases, particularly difficult ones, such as comments inside tags like <table <!--wow...a comment--> border=1> The correct solution is to specify a rule that is called after each lexical element (character, string literal, or lexical rule reference). We provide the lexer rule option ignore to let you specify the rule to use as whitespace. The solution to our HTML whitespace problem is therefore: TABLE options { ignore=WS; } : "<table" (ATTR)* '>' ; // can be protected or non-protected rule WS : ' ' | '\n' | COMMENT | ... ; We think this is cool and we hope it encourages you to do more and more interesting things in the lexer! Oh, almost forgot. There is a bug in that an extra whitespace reference is inserted after the end of a lexer alternative if the last element is an action. The effect is to include any whitespace following that token in that token's text. Tracking Line InformationEach lexer object has a line member that can be incremented by calling newline() or by simply changing its value (e.g., when processing #line directives in C). SL_COMMENT : "//" (~'\n')* '\n' {newline();} ; Do not forget to split out \n recognition when using the not operator to read until a stopping character such as: BLOCK: '(' ( '\n' { newline(); } | ~( \n | ) ) )* ') ; Another way to track line information is to override the consume() method: Tracking Column InformationANTLR (2.7.1 and beyond), tracks character column information so that each token knows what column it starts in; columns start at 1 just like line numbers. The CharScanner.consume() method asks method tab() to update the column number if it sees a tab, else it just increments the column number: ... if ( c=='\t' ) { tab(); } else { inputState.column++; } By default, tab() is defined as follows: /** advance the current column number by an appropriate amount. If you do not override this to specify how much to jump for a tab, then tabs are counted as one char. This method is called from consume(). */ public void tab() { // update inputState.column as function of // inputState.column and tab stops. // For example, if tab stops are columns 1 // and 5 etc... and column is 3, then add 2 // to column. inputState.column++; } Upon new line, the lexer needs to reset the column number to 1. Here is the default implementation of CharScanner.newline(): public void newline() { inputState.line++; inputState.column = 1; } Do not forget to call newline() in your lexer rule that matches '\n' lest the column number not be reset to 1 at the start of a line. The shared input state object for a lexer is actually the critter that tracks the column number (as well as the starting column of the current token): public class LexerSharedInputState { protected int column=1; protected int line=1; protected int tokenStartColumn = 1; protected int tokenStartLine = 1; ... } If you want to handle tabs in your lexer, just implement a method like the following to override the standard behavior. /** set tabs to 4, just round column up to next tab + 1<PHONE_NUMBER>1234567890 x x x x */ public void tab() { int t = 4; int c = getColumn(); int nc = (((c-1)/t)+1)*t+1; setColumn( nc ); } See the examples/java/columns directory for the complete example. Using Explicit LookaheadOn rare occasions, you may find it useful to explicitly test the lexer lookahead in say a semantic predicate to help direct the parse. For example, /*...*/ comments have a two character stopping symbol. The following example demonstrates how to use the second symbol of lookahead to distinguish between a single '/' and a "*/": ML_COMMENT : "/*" ( { LA(2)!='/' }? '*' | '\n' { newline(); } | ~('*'|'\n') )* "*/" ; The same effect might be possible via a syntactic predicate, but would be much slower than a semantic predicate. A DFA-based lexer handles this with no problem because they use a bunch of (what amount to) gotos whereas we're stuck with structured elements like while-loops. A Surprising Use of A Lexer: ParsingThe following set of rules match arithmetical expressions in a lexer not a parser (whitespace between elements is not allowed in this example but can easily be handled by specifying rule option ignore for each rule): EXPR { int val; } : val=ADDEXPR { System.out.println(val); } ; protected ADDEXPR returns [int val] { int tmp; } : val=MULTEXPR ( '+' tmp=MULTEXPR { val += tmp; } | '-' tmp=MULTEXPR { val -= tmp; } )* ; protected MULTEXPR returns [int val] { int tmp; } : val=ATOM ( '*' tmp=ATOM { val *= tmp; } | '/' tmp=ATOM { val /= tmp; } )* ; protected ATOM returns [int val] : val=INT | '(' val=ADDEXPR ')' ; protected INT returns [int val] : ('0'..'9')+ {val=Integer.valueOf($getText);} ; But...We've Always Used Automata For Lexical Analysis!Lexical analyzers were all built by hand in the early days of compilers until DFAs took over as the scanner implementation of choice. DFAs have several advantages over hand-built scanners:
Conversely, hand-built scanners have the following advantages over DFA implementations:
So, what approach does ANTLR 2.xx take? Neither! ANTLR 2.xx allows you to specify lexical items with expressions, but generates a lexer for you that mimics what you would generate by hand. The only drawback is that you still have to do the left-factoring for some token definitions (but at least it is done with expressions and not code). This hybrid approach allows you to build lexers that are much stronger and faster than DFA-based lexers while avoiding much of the overhead of writing the lexer yourself. In summary, specifying regular expressions is simpler and shorter than writing a hand-built lexer, but hand-built lexers are faster, stronger, able to handle unicode, and easy to debug. This analysis has led many programmers to write hand-built lexers even when DFA-generation tools such as lex and dlg are commonly-available. ANTLR 1.xx made a parallel argument concerning PDA-based LR parsers and recursive-descent LL-based parsers. As a final justification, we note that writing lexers is trivial compared to building parsers; also, once you build a lexer you will reuse it with small modifications in the future. Version: $Id: //depot/code/org.antlr/release/antlr-2.7.1/doc/lexer.html#2 $ |


This page tracks the new paper links made to my list of EGSR 2012 papers.
Page maintained by Ke-Sen Huang.
If you have additions or changes, send an e-mail.
September 16, 2012
- Intrinsic Images by Clustering
August 4, 2012
- Example-Based Fractured Appearance
(
)
()
July 29, 2012
- Artistic Illumination Transfer for Portraits
July 14, 2012
- Example-Based Fractured Appearance
July 11, 2012
- Analytic Tangent Irradiance Environment Maps for Anisotropic Surfaces
- A Statistical Method for SVBRDF Approximation from Video Sequence in General Lighting Conditions
- Tessellation-Independent Smooth Shadow Boundaries
July 9, 2012
- Polynomial Optics: A Toolkit for Efficient Ray-Tracing of Lens Systems
- Matting and Compositing for Fresnel Reflection on Wavy Surfaces
June 28, 2012
- ISHair: Importance Sampling for Hair Scattering
()
(
)
June 24, 2012
- Progressive Virtual Beam Lights
- Pre-convolved Radiance Caching
June 21, 2012
- Importance Sampling Techniques for Path Tracing in Participating Media
June 20, 2012
- Surface Relief Analysis for Illustrative Shading
June 16, 2012
- Per-Vertex Defocus Blur for Stochastic Rasterization
- ISHair: Importance Sampling for Hair Scattering
June 5, 2012
- Polynomial Optics: A Toolkit for Efficient Ray-Tracing of Lens Systems
June 4, 2012
- Parameterization-Aware MIP-Mapping
- Progressive Virtual Beam Lights
- Accurate fitting of measured reflectances using a Shifted Gamma micro-facet distribution
- Gamut Mapping Spatially Varying Reflectance with an Improved BRDF Similarity Metric
- Geometry Presorting for Implicit Object Space Partitioning
- Quantized Point-Based Global Illumination
- Tessellation-Independent Smooth Shadow Boundaries
May 29, 2012
- Accurate fitting of measured reflectances using a Shifted Gamma micro-facet distribution
- Page published
kesen.huang@gmail.com


| I l@ve RuBoard |
In this section string means the actual string class. It might be string, wstring, or any other specialization of class basic_string<>. Type char means the actual character type, which is char for string and wchar_t for wstring. Other types and values that are in italic type have definitions that depend on individual definitions of the character type or traits class. The details about traits classes are provided in Section 14.1.2.
string::traits_type
The type of the character traits.
The second template parameter of class basic_string.
For type string, it is equivalent to char_traits<char>.
string::value_type
The type of the characters.
It is equivalent to traits_type::char_type.
For type string, it is equivalent to char.
string::size_type
The unsigned integral type for size values and indices.
It is equivalent to allocator_type::size_type.
For type string, it is equivalent to size_t.
string::difference_type
The signed integral type for difference values.
It is equivalent to allocator_type::difference_type.
For type string, it is equivalent to ptrdiff_t.
string::reference
The type of character references.
It is equivalent to allocator_type::reference.
For type string, it is equivalent to char&.
string::const_reference
The type of constant character references.
It is equivalent to allocator_type::const_reference.
For type string, it is equivalent to const char&.
string::pointer
The type of character pointers.
It is equivalent to allocator_type::pointer.
For type string, it is equivalent to char*.
string::const_pointer
The type of constant character pointers.
It is equivalent to allocator_type::const_pointer.
For type string, it is equivalent to const char*.
string::iterator
The type of iterators.
The exact type is implementation defined.
For type string, it is typically char*.
string::const_iterator
The type of constant iterators.
The exact type is implementation defined.
For type string, it is typically const char*.
string::reverse_iterator
The type of reverse iterators.
It is equivalent to reverse_iterator<iterator>.
string::const_reverse_iterator
The type of constant reverse iterators.
It is equivalent to reverse_iterator<const_iterator>.
static const size_type string::npos
A special value that indicates one of the following:
"not found"
"all remaining characters"
It is an unsigned integral value that is initialized by -1.
Be careful when you use npos. See Section 11.2.12, for details.
string::string ()
The default constructor.
Creates an empty string.
string::string (const string& str)
The copy constructor.
Creates a new string as a copy of str.
string::string (const string& str, size_type str_idx)
string::string (const string& str, size_type str_idx, size_type str_num)
Create a new string that is initialized by, at most, the first str_num characters of str starting with index str_idx.
If str_num is missing, all characters from str_idx to the end of str are used.
Throws out_of_range if str_idx > str.size().
string::string (const char* cstr)
Creates a string that is initialized by the C-string cstr.
The string is initialized by all characters of cstr up to but not including '\0'.
Note that cstr may not be a null pointer (NULL).
Throws length_error if the resulting size exceeds the maximum number of characters.
string::string (const char* chars, size_type chars_len)
Creates a string that is initialized by chars_len characters of the character array chars.
Note that chars must have at least chars_len characters. The characters may have arbitrary values. Thus, '\0' has no special meaning.
Throws length_error if chars_len is equal to string::npos.
Throws length_error if the resulting size exceeds the maximum number of characters.
string::string (size_type num, char c)
Creates a string that is initialized by num occurrences of character c.
Throws length_error if num is equal to string::npos.
Throws length_error if the resulting size exceeds the maximum number of characters.
string ::string (InputIterator beg, Input Iterator end)
Creates a string that is initialized by all characters of the range [beg,end).
Throws length_error if the resulting size exceeds the maximum number of characters.
string::~string ()
The destructor.
Destroys all characters and frees the memory.
Most constructors allow you to pass an allocator as an additional argument (see Section 11.3.12).
size_type string::size () const
size_type string::length () const
Both functions return the actual number of characters.
They are equivalent.
To check whether the string is empty, you should use empty() because it might be faster.
bool string::empty () const
Returns whether the string is empty (contains no characters).
It is equivalent to string::size()==0, but it might be faster.
size_type string::max_size () const
Returns the maximum number of characters a string could contain.
Whenever an operation results in a string that has a length greater than max_size(), the class throws length_error.
size_type string::capacity () const
Returns the number of characters the string could contain without reallocation.
void string::reserve ()
Void string::reserve (size_type num)
The second form reserves internal memory for at least num characters.
If num is less than the actual capacity, the call is taken as a nonbinding request to shrink the capacity.
If num is less than the current number of characters, the call is taken as a nonbinding request to shrink the capacity to fit the actual number of characters.
If no argument is passed, the call is always a nonbinding shrink-to-fit request.
The capacity is never reduced below the current number of characters.
Each reallocation invalidates all references, pointers, and iterators and takes some time, so a preemptive call to reserve() is useful to increase speed and to keep references, pointers, and iterators valid (see Section 11.2.5, for details).
bool comparison (const string& str1, const string& str2)
bool comparison (const string& str, const char* cstr)
bool comparison (const char* cstr, const string& str)
The first form returns the result of the comparison of two strings.
The second and third form return the result of the comparison of a string with a C-string.
comparison might be any of the following:
Operator == operator != operator < operator > operator <= operator >=
The values are compared lexicographically (see page 488).
int string::compare (const string& str) const
Compares the string *this with the string str.
Returns
0 if both strings are equal
A value < 0 if *this is lexicographically less than str
A value > 0 if *this is lexicographically greater than str
For the comparison, traits::compare() is used (see Section 14.1.2).
See Section 11.2.7, for details.
int string::compare (size_type idx, size_type len, const string& str) const
Compares, at most, len characters of string *this, starting with index idx with the string str.
Throws out_of_range if idx > size().
The comparison is performed as just described for compare (str).
int string::compare (size_type idx, size_type len, const string& str, size_type str_idx, size_type str_len) const
Compares, at most, len characters of string *this, starting with index idx with, at most, str_len characters of string str starting with index str_idx.
Throws out_of_range if idx > size().
Throws out_of_range if str_idx > str.size().
The comparison is performed as just described for compare (str).
int string::compare (const char* cstr) const
Compares the characters of string *this with the characters of the C-string cstr.
The comparison is performed as just described for compare (str).
int string::compare (size_type idx, size_type len, const char* cstr) const
Compares, at most, len characters of string *this, starting with index idx with all characters of the C-string cstr.[8]
[8] The standard specifies the behavior of this form of compare() differently: It states that cstr is not considered a C-string but a character array, and passes npos as its length (in fact, it calls the following form of compare() by using npos as an additional parameter). This is a bug in the standard (it would always throw a length_error exception).
The comparison is performed as just described for compare(str).
Note that cstr may not be a null pointer (NULL).
int string::compare (size_type idx,size_type len, const char* chars, size_type chars_len)const
Compares, at most, len characters of string *this, starting with index idx with chars_len characters of the character array chars.
The comparison is performed as just described for compare(str).
Note that chars must have at least chars_len characters. The characters may have arbitrary values. Thus, '\0' has no special meaning.
Throws length_error if chars_len is equal to string::npos.
char& string::operator [ ] (size_type idx)
char string::operator [ ] (size_type idx) const
Both forms return the character with the index idx (the first character has index 0).
For constant strings, length() is a valid index and the operator returns the value generated by the default constructor of the character type (for string: '\0').
For nonconstant strings, using length() as index value is invalid.
Passing an invalid index results in undefined behavior.
The reference returned for the nonconstant string may become invalidated due to string modifications or reallocations (see Section 11.2.6, for details).
If the caller can't ensure that the index is valid, at() should be used.
char& string::at (size_type idx)
const char& string::at (size_type idx) const
Both forms return the character that has the index idx (the first character has index 0).
For all strings, an index with length() as value is invalid.
Passing an invalid index (less than 0 or greater than or equal to size()) throws an out_of_range exception.
The reference returned for the nonconstant string may become invalidated due to string modifications or reallocations (see Section 11.2.6, for details).
If the caller ensures that the index is valid, she can use operator [], which is faster.
const char* string::c_str () const
Returns the contents of the string as a C-string (an array of characters that has the null character '\0' appended).
The return value is owned by the string. Thus, the caller must neither modify nor free or delete the return value.
The return value is valid only as long as the string exists, and as long as only constant functions are called for it.
const char* string::data () const
Returns the contents of the string as a character array.
The return value contains all characters of the string without any modification or extension. In particular, no null character is appended. Thus, the return value is, in general, not a valid C-string.
The return value is owned by the string. Thus, the caller must neither modify nor free or delete the return value.
The return value is valid only as long as the string exists, and as long as only constant functions are called for it.
size_type string::copy (char* buf, size_type buf_size) const
size_type string::copy (char* buf, size_type buf_size, size_type idx) const
Both forms copy, at most, buf_size characters of the string (beginning with index idx) into the character array buf.
They return the number of characters copied.
No null character is appended. Thus, the contents of buf may be not a valid C-string after the call.
The caller must ensure that buf has enough memory; otherwise, the call results in undefined behavior.
Throws out_of_range if idx > size().
string& string::operator = (const string& str)
string& string::assign (const string& str)
Both operations assign the value of string str.
They return *this.
string& string::assign (const string& str, size_type str_idx, size_type str_num)
Assigns at most str_num characters of str starting with index str_idx.
Returns *this.
Throws out_of _range if str_idx > str. size().
string & string:: operator = (const char* cstr)
string & string::assign (const char* cstr)
Both operations assign the characters of the C-string cstr.
They assign all characters of cstr up to but not including '\0'.
Both operations return *this.
Note that cstr may not be a null pointer (NULL).
Both operations throw length_error if the resulting size exceeds the maximum number of characters.
string& string::assign (const char* chars, size_type chars_len)
Assigns chars_len characters of the character array chars.
Returns *this.
Note that chars must have at least chars_len characters. The characters may have arbitrary values. Thus, '\0' has no special meaning.
Throws length_error if the resulting size exceeds the maximum number of characters.
string& string:: operator = (char c)
Assigns character c as the new value.
Returns *this.
After this call, *this contains only this single character.
string & string::assign (size_type num, char c)
Assigns num occurrences of character c.
Returns *this.
Throws length_error if num is equal to string::npos.
Throws length_error if the resulting size exceeds the maximum number of characters.
void string::swap (string& str)
void swap (string& str1, string& str2)
Both forms swap the value of two strings:
The member function swaps the contents of *this and str.
The global function swaps the contents of str1 and str2.
You should prefer these functions over assignment if possible because they are faster. In fact, they are guaranteed to have constant complexity. See Section 11.2.8, for details.
string& string::operator += (const string& str)
string& string::append (const string& str)
Both operations append the characters of str.
They return *this.
Both operations throw length_error if the resulting size exceeds the maximum number of characters.
string& string::append (const string& str, size_type str_idx, size_type str_num)
Appends, at most, str_num characters of str, starting with index str_idx.
Returns *this.
Throws out_of_range if str_idx > str. size().
Throws length_error if the resulting size exceeds the maximum number of characters.
string& string:: operator += (const char* cstr)
string& string::append (const char* cstr)
Both operations append the characters of the C-string cstr.
They return *this.
Note that cstr may not be a null pointer (NULL).
Both operations throw length_error if the resulting size exceeds the maximum number of characters.
string& string::append (const char* chars, size_type chars_len)
Appends chars_len characters of the character array chars.
Returns *this.
Note that chars must have at least chars_len characters. The characters may have arbitrary values. Thus, '\0' has no special meaning.
Throws length_error if the resulting size exceeds the maximum number of characters.
string& string::append (size_type num, char c)
Appends num occurrences of character c.
Returns *this.
Throws length_error if the resulting size exceeds the maximum number of characters.
string& string::operator += (char c)
void string:: push_back (char c)
Both operations append character c.
Operator += returns *this.
Both operations throw length_error if the resulting size exceeds the maximum number of characters.
string& string::append (InputIterator beg, InputIterator end)
Appends all characters of the range [beg,end).
Returns *this.
Throws length_error if the resulting size exceeds the maximum number of characters.
string& string::insert (size_type idx, const string& str)
Inserts the characters of str so that the new characters start with index idx.
Returns *this.
Throws out_of_range if idx > size().
Throws length_error if the resulting size exceeds the maximum number of characters.
string& string::insert (size_type idx, const string& str, size_type str_idx, size_type str_num)
Inserts, at most, str_num characters of str, starting with index str_idx, so that the new characters start with index idx.
Returns *this.
Throws out_of_range if idx > size().
Throws out_of_range if str_idx > str.size().
Throws length_error if the resulting size exceeds the maximum number of characters.
string& string::insert (size_ type idx, const char* cstr)
Inserts the characters of the C-string cstr so that the new characters start with index idx.
Returns *this.
Note that cstr may not be a null pointer (NULL).
Throws out_of_range if idx > size().
Throws length_error if the resulting size exceeds the maximum number of characters.
string& string::insert (size_type idx, const char* chars, size_type chars_len)
Inserts chars_len characters of the character array chars so that the new characters start with index idx.
Returns *this.
Note that chars must have at least chars_len characters. The characters may have arbitrary values. Thus, '\0' has no special meaning.
Throws out_of_range if idx > size().
Throws length_error if the resulting size exceeds the maximum number of characters.
string& string ::insert (size_type idx, size_type num, char c)
void string ::insert (iterator pos, size_type num, char c)
Both forms insert num occurrences of character c at the position specified by idx or pos respectively.
The first form inserts the new characters so that they start with index idx.
The second form inserts the new characters before the character to which iterator pos refers.
Note that the overloading of these two functions results in a possible ambiguity. If you pass 0 as first argument, it can be interpreted as an index (which is typically a conversion to unsigned) or as an iterator (which is often a conversion to char*). So in this case you should pass an index as the exact type. For example:
string s; ... s.insert (0,1, ' ') ; //ERROR: ambiguous s.insert((string::size_type)0,1,' '); //OK
Both forms return *this.
Both forms throw out_of_range if idx > size().
Both forms throw length_error if the resulting size exceeds the maximum number of characters.
iterator string ::insert (iterator pos, char c )
Inserts a copy of character c before the character to which iterator pos refers.
Returns the position of the character inserted.
Throws length_error if the resulting size exceeds the maximum number of characters.
void string ::insert (iterator pos, InputIterator beg, InputIterator end )
Inserts all characters of the range [ beg,end ) before the character to which iterator pos refers.
Throws length_error if the resulting size exceeds the maximum number of characters.
void string ::clear ()
string& string ::erase ()
Both functions delete all characters of the string. Thus, the string is empty after the call.
erase() returns *this.
string& string ::erase (size_type idx )
string& string ::erase (size_type idx, size_type len )
Both forms erase, at most, len characters of *this, starting at index idx.
They return *this.
If len is missing, all remaining characters are removed.
Both forms throw out_of_range if idx > size().
string& string ::erase (iterator pos)
string& string ::erase (iterator beg, iterator end )
Both forms erase the single character at iterator position pos or all characters of the range [ beg,end) respectively.
They return the first character after the last character removed (thus, the second form returns end)[9]
[9] The standard specifies that the second form of this function returns the position after end. This is a bug in the standard.
void string ::resize (size_type num)
void string ::resize (size_type num, char c )
Both forms change the number of characters of *this to num. Thus, if num is not equal to size(), they append or remove characters at the end according to the new size.
If the number of characters increases, the new characters are initialized by c. If c is missing, the characters are initialized by the default constructor of the character type (for string: '\0').
Both forms throw length_error if num is equal to string ::npos.
Both forms throw length_error if the resulting size exceeds the maximum number of characters.
string& string ::replace (size_type idx, size_type len, const string& str)
string& string ::replace (iterator beg, iterator end, const string& str)
The first form replaces, at most, len characters of *this, starting with index idx, with all characters of str.
The second form replaces all characters of the range [ beg,end) with all characters of str.
Both forms return *this.
Both forms throw out_of_range if idx > size().
Both forms throw length_error if the resulting size exceeds the maximum number of characters.
string& string::replace (size_type idx, size_type len, const string& str, size_type str_idx, size_type str_num)
Replaces, at most, len characters of *this, starting with index idx, with at most str_num characters of str starting with index str_idx.
Returns *this.
Throws out_of_range if idx > size().
Throws out_of_range if str_idx > str. size().
Throws length_error if the resulting size exceeds the maximum number of characters.
string& string::replace (size_type idx, size_type len, const char* cstr)
string& string::replace (iterator beg, iterator end, const char* cstr)
Both forms replace, at most, len characters of *this, starting with index idx, or all characters of the range [beg,end), respectively, with all characters of the C-string cstr.
Both forms return *this.
Note that cstr may not be a null pointer (NULL).
Both forms throw out_of_range if idx > size().
Both forms throw length_error if the resulting size exceeds the maximum number of characters.
string& string::replace (size_type idx, size_type len, const char* chars, size_type chars_len)
string& string::replace (iterator beg, iterator end, const char* chars, size_type chars_len)
Both forms replace, at most, len characters of *this, starting with index idx, or all characters of the range [beg,end), respectively, with chars_len characters of the character array chars.
They return *this.
Note that chars must have at least chars_len characters. The characters may have arbitrary values. Thus, '\0' has no special meaning.
Both forms throw out_of_range if idx > size().
Both forms throw length_error if the resulting size exceeds the maximum number of characters.
string& string::replace (size_type idx, size_type len, size_type num, char c)
string& string::replace (iterator beg, iterator end, size_type num, char c)
Both forms replace, at most, len characters of *this, starting with index idx, or all characters of the range [beg,end), respectively, with num occurrences of character c
They return *this.
Both forms throw out_of_range if idx > size().
Both forms throw length_error if the resulting size exceeds the maximum number of characters.
string& string::replace (iterator beg, iterator end InputIterator newBeg, InputIterator newEnd)
Replaces all characters of the range [beg,end) with all characters of the range [newBeg,newEnd).
Returns *this.
Throws length_error if the resulting size exceeds the maximum number of characters.
size_type string::find (char c) const
size_type string::flnd (char c, size_type idx) const
size_type string::rfind (char c) const
size_type string::rfind (char c, size_type idx) const
These functions search for the first/last character c (starting at index idx).
The find() functions search forward and return the first substring.
The find() functions search backward and return the last substring.
These functions return the index of the character when successful or string::npos if they fail.
size_type string::find (const string& str) const
size_type string::find (const string& str, size_type idx) const
size_type string::rfind (const string& str) const
size_type string::rfind (const string& str, size_type idx) const
These functions search for the first/last substring str (starting at index idx).
The find() functions search forward and return the first substring.
The find() functions search backward and return the last substring.
These functions return the index of the first character of the substring when successful or string::npos if they fail.
size_type string::find (const char* cstr) const
size_type string::find (const char* cstr, size_type idx) const
size_type string::rfind (const char* cstr) const
size_type string::rfind (const char* cstr, size_type idx) const
These functions search for the first/last substring that has the characters of the C-string cstr (starting at index idx).
The find() functions search forward and return the first substring.
The rfind() functions search backward and return the last substring.
These functions return the index of the first character of the substring when successful or string::npos if they fail.
Note that cstr may not be a null pointer (NULL).
size_type string::find (const char* chars, size_type idx, size_type chars_len) const
size_type string::rfind (const char* chars, size_type idx, size_type chars_len) const
These functions search for the first/last substring that has chars_len characters of the character array chars (starting at index idx).
find() searches forward and returns the first substring.
find() searches backward and returns the last substring.
These functions return the index of the first character of the substring when successful or string::npos if they fail.
Note that chars must have at least chars_len characters. The characters may have arbitrary values. Thus, '\0' has no special meaning.
size_type string::find_first_of (const string& str) const
size_type string::find_first_of (const string& str, size_type idx) const
size_type string::find_first_not_of (const string& str) const
size_type string::find_first_not_of (const string& str, size_type idx) const
These functions search for the first character that is or is not also an element of the string str (starting at index idx).
These functions return the index of that character or substring when successful or string::npos if they fail.
size_type string:: find_first_of (const char* cstr) const
size_type string::find_first_of (const char* cstr, size_type idx) const
size_type string::find_first_not_of (const char* cstr) const
size_type string:: find_first_not_of (const char* cstr, size_type idx) const
These functions search for the first character that is or is not also an element of the C-string cstr (starting at index idx).
These functions return the index of that character when successful or string::npos if they fail.
Note that cstr may not be a null pointer (NULL).
size_type string::find_first_of (const char* chars, size_type idx, size_type chars_len) const
size_type string::find_first_not_of (const char* chars, size_type idx, size_type chars_len) const
These functions search for the first character that is or is not also an element of the chars_len characters of the character array chars (starting at index idx).
These functions return the index of that character when successful or string::npos if they fail.
Note that chars must have at least chars_len characters. The characters may have arbitrary values. Thus, '\0' has no special meaning.
size_type string::find_first_of (char c) const
size_type string::find_first_of (char c, size_type idx) const
size_type string::find_first_not_of (char c) const
size_type string::find_first_not_of (char c, size_type idx) const
These functions search for the first character that has or does not have the value c (starting at index idx).
These functions return the index of that character when successful or string::npos if they fail.
size_type string::find_last_of (const string& str) const
size_type string::find_last_of (const string& str, size_type idx) const
size_type string::find_last_not_of (const string& str) const
size_type string::find_last_not_of (const string& str, size_type idx) const
These functions search for the last character that is or is not also an element of the string str (starting at index idx).
These functions return the index of that character or substring when successful or string::npos if they fail.
size_type string::find_last_of (const char* cstr) const
size_type string::find_last_of (const char* cstr, size_type idx) const
size_type string::find_last_not_of (const char* cstr) const
size_type string::find_last_not_of (const char* cstr, size_type idx) const
These functions search for the last character that is or is not also an element of the C-string cstr (starting at index idx).
These functions return the index of that character when successful or string::npos if they fail.
Note that cstr may not be a null pointer (NULL).
size_type string::find_last_of (const char* chars, size_type idx, size_type chars_len) const
size_type string::find_last_not_of (const char* chars, size_type idx, size_type chars_len) const
These functions search for the last character that is or is not also an element of the chars_len characters of the character array chars (starting at index idx).
These functions return the index of that character when successful or string::npos if they fail.
Note that chars must have at least chars_len characters. The characters may have arbitrary values. Thus, '\0' has no special meaning.
size_type string::find_last_of ( char c) const
size_type string::find_last_of (char c, size_type idx) const
size_type string::find_last_not_of (char c) const
size_type string::find_last_not_of (char c, size_type idx) const
These functions search for the last character that has or does not have the value c (starting at index idx).
These functions return the index of that character when successful or string::npos if they fail.
string string::substr () const
string string::substr (size_type idx) const
string string::substr (size_type idx, size_type len) const
All forms return a substring of, at most, len characters of the string *this starting with index idx.
If len is missing, all remaining characters are used.
If idx and len are missing, a copy of the string is returned.
All forms throw out_of_range if idx > size().
string operator + (const string& str1, const string& str2)
string operator + (const string& str, const char* cstr)
string operator + (const char* cstr, const string& str)
string operator + (const string& str, char c)
string operator + (char c, const string& str)
All forms concatenate all characters of both operands and return the sum string.
The operands may be any of the following:
A string
A C-string
A single character
All forms throw length_error if the resulting size exceeds the maximum number of characters.
ostream& operator<< (ostream& strm, const string& str)
Writes the characters of str to the stream strm.
If strm.width() is greater than 0, at most width() characters are written and width() is set to 0.
ostream is the ostream type basic_ostream<char> according to the character type (see Section 13.2.1).
istream& operator >> (istream& strm, string& str)
Reads the characters of the next word from strm into the string str.
If the skipws flag is set for strm, leading whitespaces are ignored.
Characters are extracted until any of the following happens:
strm.width() is greater than 0 and width() characters are stored
strm. good() is false (which might cause an appropriate exception)
isspace (c, strm. getloc()) is true for the next character c
str.max_size() characters are stored
The internal memory is reallocated accordingly.
istream is the istream type basic_istream<char> according to the character type (see Section 13.2.1).
istream& getline (istream& strm, string& str)
istream& getline (istream& strm, string& str, char delim)
Read the characters of the next line from strm into the string str.
All characters (including leading whitespaces) are extracted until any of the following happens:
strm. width() is greater than 0 and width() characters are stored
strm.good() is false (which might cause an appropriate exception)
delim or strm. widen('\n') is extracted
str.max_size() characters are stored
The line delimiter is extracted but not appended.
The internal memory is reallocated accordingly.
istream is the istream type basic_istream<char> according to the character type (see Section 13.2.1).
iterator string::begin ()
const_iterator string::begin() const
Both forms return a random access iterator for the beginning of the string (the position of the first character).
If the string is empty, the call is equivalent to end().
iterator string::end ()
const_iterator string::end() const
Both forms return a random access iterator for the end of the string (the position after the last character).
Note that the character at the end is not defined. Thus, *s. end() results in undefined behavior.
If the string is empty, the call is equivalent to begin().
reverse_iterator string::rbegin ()
const_reverse_iterator string::rbegin () const
Both forms return a random access iterator for the beginning of a reverse iteration over the string (the position of the last character).
If the string is empty, the call is equivalent to rend().
For details about reverse iterators see Section 7.4.1.
reverse_iterator string::rend ()
const_reverse_iterator string::rend () const
Both forms return a random access iterator for the end of the reverse iteration over the string (the position before the first character).
Note that the character at the reverse end is not defined. Thus, *s.rend() results in undefined behavior.
If the string is empty, the call is equivalent to rbegin().
For details about reverse iterators see Section 7.4.1.
Strings provide the usual members of classes with allocator support.
string::allocator_type
The type of the allocator.
Third template parameter of class basic_string<>.
For type string, it is equivalent to allocator<char>.
allocator_type string::get_allocator () const
Returns the memory model of the string.
Strings also provide all constructors with optional allocator arguments. The following are all of the string constructors, including their optional allocator arguments, according to the standard:
namespace std { template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > class basic_string { public: //default constructor explicit basic_string(const Allocator& a = Allocator()); //copy constructor and substrings basic_string(const basic_string& str, size_type str_idx = 0, size_type str_num = npos); basic_string(const basic_string& str, size_type str_idx, size_type str_nnm, const Allocator&); //constructor for C-strings basic_string(const charT* cstr, const Allocator& a = Allocator()); //constructor for character arrays basic_string(const charT* chars, size_type chars_len, const Allocator& a = Allocator()); //constructor for num occurrences of a character basic_string(size_type num, charT c, const Allocator& a = Allocator()); // constructor for a range of characters template<class InputIterator> basic_string(InputIterator beg, InputIterator end, const Allocator& a = Allocator()); ... }; }
These constructors behave as described in Section 11.3.2, with the additional ability that you can pass your own memory model object. If the string is initialized by another string, the allocator also gets copied.[10] See Chapter 15 for more details about allocators.
[10] The original standard states that the default allocator is used when a string gets copied. However, this does not make much sense, so this is the proposed resolution to fix this behavior.
| I l@ve RuBoard |


We build mobile and web applications for you. From large scale enterprise organisations to niche startups and SMEs, we have a proven track record for delivery
Genox provide development services and solutions for both web and mobile apps. We are Google Cloud Certified and also an IBM Business Partner
Utilising modern web frameworks and technologies with a keen focus on open source but using proprietary software where advantageous; we work closely with our clients to deliver their application to expectations
Our expertise encompasses the full stack; from databases, RESTFul APIs and backend server infrastructure to client side application UI/UX and front end development


{# LIST VIEW OF ALL shows #} {# You can find a full list of variables to use on this page in your CMS. #} {% extends "templates/partials/base.html" %} {% block content %}
{{ item.url_of_video.description|striptags|truncate(100) }}


Some basic programmes that are used in this web site in HTML will be explained here.
- At the start of every programme this has to be written

<title>.....</title>

This is the start and framework of every web page before any designing is done. This has to be implemented.
2.All about divs and what not

These are normally used to contain other code in the website. All code must be writen in between these in other to work.
(b) identifying divs`

This simply allows you to identify each of the divs and colour or style them seperatly.
3.linking
There are different types of linking methods for different purposes
(a) Linking CSS files
<link rel="stylesheet" type="text/css" href="style.css">
so far This is the only kind of file refrence I have learned. CSS files are used to style a page so that it is not so blank.
the rel=“stylesheet” means that the file is used to syle the page. type=“text/css” simply states the type and programme nature of the file. Lastly href=“style.css” means to state that the refrence file is to this location which is placed between the “”.
(b) Linking with
This is a link
The link’s destination is specified in the href attribute. Attributes are used to provide additional information about HTML elements.
4.images

Images are always placed in this format. the scr="" is where the file location of the image will be. the style="" refers to the sizing of the image when displayed on the web page.
- Conecting to other pages

Home

About

Website

Development

3D Printing

2D Cutting

Embedded Prog

Project

When linking to other web pages the ul tag must be used within a div.

This is the link tag for pages when your web site has more then one page.
link
this line is used to define and help the computer find the file that you want to open when you click on the link.


NXT Websocket client
Websocket URL :
Connect to WS
Connect EV3
Connect NXT
Start motor
Stop motor
Sensor reques
Mapping
Loop the command
Stop loop
Console


OUR JOURNEY TILL NOW
In 1990, Microsoft introduced the Microsoft Office suite which bundled separate applications such as Microsoft Word and Microsoft Excel.[15]:301 On May 22, Microsoft launched Windows 3.0, featuring streamlined user interface graphics and improved protected mode capability for the Intel 386 processor,[35] and both Office and Windows became dominant in their respective areas.[3
In July 2012, Microsoft sold its 50% stake in MSNBC, which it had run as a joint venture with NBC since 1996.[77] On October 1, Microsoft announced its intention to launch a news operation, part of a new-look MSN, with Windows 8 later in the month.[78] On October 26, 2012, Microsoft launched Windows 8 and the Microsoft Surface.[73][79] Three days later, Windows Phone 8 was launched.[80] To cope with the potential for an increase in demand for products and services, Microsoft opened a number of "holiday stores" across the U.S. to complement the increasing number of "bricks-and-mortar" Microsoft Stores that opened in 2012.[81] On March 29, 2013, Microsoft launched a Patent Tracker.[82
Some Features That Made Us Unique
Our Projects in different Domains
2345
App
6784
Web
1056
IOT
9152
MACHINE LEARNING
UPCOMING EVENTS
YOU WANT TO LEARN , COME WE ARE HERE
Download Our App for all Platform
VINNOVATE IT is launching an Office mobile app today for Android and iOS designed to make some of its signature software — Word, Excel and PowerPoint — must-have tools for all smartphone users. Microsoft first unveiled the Office app at its Ignite conference
Desktop
On website
On Mobile
On Play Store
Meet our Board Members
OUR EXPERT TEAM


|
My Project
|
Go to the source code of this file.
Classes | |
| struct | nn_worker_timer |
Macros | |
| #define | NN_WORKER_TIMER_TIMEOUT 1 |
| #define | NN_WORKER_TASK_EXECUTE 1 |
Functions | |
| void | nn_worker_timer_init (struct nn_worker_timer *self, struct nn_fsm *owner) |
| void | nn_worker_timer_term (struct nn_worker_timer *self) |
| int | nn_worker_timer_isactive (struct nn_worker_timer *self) |
| void | nn_worker_task_init (struct nn_worker_task *self, int src, struct nn_fsm *owner) |
| void | nn_worker_task_term (struct nn_worker_task *self) |
| int | nn_worker_init (struct nn_worker *self) |
| void | nn_worker_term (struct nn_worker *self) |
| void | nn_worker_execute (struct nn_worker *self, struct nn_worker_task *task) |
| void | nn_worker_cancel (struct nn_worker *self, struct nn_worker_task *task) |
| void | nn_worker_add_timer (struct nn_worker *self, int timeout, struct nn_worker_timer *timer) |
| void | nn_worker_rm_timer (struct nn_worker *self, struct nn_worker_timer *timer) |
| #define NN_WORKER_TASK_EXECUTE 1 |
| #define NN_WORKER_TIMER_TIMEOUT 1 |
| void nn_worker_add_timer | ( | struct nn_worker * | self, |
| int | timeout, | ||
| struct nn_worker_timer * | timer | ||
| ) |
| void nn_worker_cancel | ( | struct nn_worker * | self, |
| struct nn_worker_task * | task | ||
| ) |
| void nn_worker_execute | ( | struct nn_worker * | self, |
| struct nn_worker_task * | task | ||
| ) |
| int nn_worker_init | ( | struct nn_worker * | self | ) |
| void nn_worker_rm_timer | ( | struct nn_worker * | self, |
| struct nn_worker_timer * | timer | ||
| ) |
| void nn_worker_task_init | ( | struct nn_worker_task * | self, |
| int | src, | ||
| struct nn_fsm * | owner | ||
| ) |
| void nn_worker_task_term | ( | struct nn_worker_task * | self | ) |
| void nn_worker_term | ( | struct nn_worker * | self | ) |
| void nn_worker_timer_init | ( | struct nn_worker_timer * | self, |
| struct nn_fsm * | owner | ||
| ) |
| int nn_worker_timer_isactive | ( | struct nn_worker_timer * | self | ) |
| void nn_worker_timer_term | ( | struct nn_worker_timer * | self | ) |