-
Notifications
You must be signed in to change notification settings - Fork 0
Parser Command Reference
A .froley file should have one parser section which is comprised of any number of routines.
The Parser turns a token stream into an Abstract Syntax Tree (AST) of extended Cmd nodes.
- routine_name
... # commands
- another_routine
...
- routine3
if (...) return # returns 0 by default
if (...) return 5 # can return any integer
if (...) return true # 'true' and 'false' are returned as '1' and '0'
- routine4
if (routine3) println "success"
The topmost routine is the default routine. It is called to parse a token stream by default; other Parser routines may be explicitly called if desired.
Routines cannot accept arguments - use global variables if needed. Routines implicitly return an integer. return returns "0" by default.
Parser routines automatically return at the end if no explicit return command is given.
count = 0
if (consume('{')) ++count
...
- Variables are created simply by assigning a value to a name.
- All variables are global variables (accessible to all Parser routines).
- Variables are statically typed. The static type of a variable is implicitly determined by the type of the first value assigned it.
- Variables can be used to pass values into or out of routines.
| Name | Description |
|---|---|
| content | Read-only. See Creating Nodes. |
| disable_output | Incrementing or setting to non-zero causes node creation commands to have no effect (createNull, produce NodeType(...), produceList, etc.). This allows parsing through source code for purposes other than creating an AST. |
| Example | Description |
|---|---|
"abc" |
A String |
'a' |
A Character |
123 |
An Integer |
true |
Logical true |
false |
Logical false |
`(-1.0).acos` |
A Native Literal expression (see Creating Nodes) |
Strings and Characters are mostly interchangeable. The only caveat is if the initial value of a variable is a Character, it will not be able to later store a String.
| Statement | Description |
|---|---|
++ |
Increment operator. Increment variables with ++varname or varname++. |
-- |
Decrement operator. Decrement variables with --varname or varname--. |
-> NodeType(...)
|
-> is an alias for produce. |
| create NodeType create NodeType(args) |
Push a new Cmd node on the internal stack and continue execution. See Creating Nodes. |
| createList createList ListType |
Creates a CmdList or extended CmdList node that contains all the nodes on the stack since the most recent beginList command. The resulting list is pushed back on the stack. |
| createNull | Pushes a null reference onto the node stack. |
| createTokenList | Pushes a TokenList node onto the node stack that contains all the .tokens:Token[] that have been read since the most recent call to savePosition. The saved position is consumed and the command stack is discarded back to the save position. See also createTokenListPreservingStack and produceTokenList. |
| createTokenListPreservingStack | Like createTokenList but preserves the command stack's contents. |
| discardList | Cancels the most recent beginList. The stack is unaltered. |
| discardPosition | Discards the most recent savePosition. |
| mustConsume("symbol") mustConsume(TOKEN_TYPE) |
If the next token matches the specified type, read and discard it. Otherwise throw an error. |
| mustConsume(@"content") | If the string [content] of the next token matches the specified type, read and discard it. Otherwise throw an error. |
| noAction | Does nothing. Useful as a placeholder single command for if & while. |
| pop varname | Pops a Cmd node off the command stack and stores it in varname, which will be automatically created as a global variable if it doesn't already exist. |
| print arg1 [arg2...] | Prints one or more expressions without a newline. |
| println arg1 [arg2...] | Prints one or more expressions followed by a newline. |
| produce NodeType produce NodeType(args) |
Executes a create NodeType(...) and then returns from the current routine. |
| produceNull | Pushes a null reference on the stack and then returns from the current routine. |
| produceList produceList ListType |
Executes a createList ... and then returns from the current routine. |
| produceTokenList | Executes createTokenList and then returns from the current routine. |
| produceTokenListPreservingStack | Executes createTokenListPreservingStack and then returns from the current routine. |
| push varname | Pushes the Cmd node value of variable varname onto the command stack. |
| restorePosition | Rewinds the input to the point of the most recent savePosition. |
| return | Returns from the current routine. If execution reaches the end of a parser routine a return happens automatically. |
| savePosition | Saves the current input position (line and column, etc.) to be either rewound to with restorePosition or else discarded with discardPosition. |
| syntaxError syntaxError "message" |
Throws a CompileError with either a default "unexpected input" message or a custom message. |
| Control Structure | Description |
|---|---|
| if (condition) ... elseIf (condition) ... else ... |
Single line if statement; separate multiple commands with ;. |
| if (condition) ... elseIf (condition) ... else ... endIf |
Multi-line line if statement. |
| on token‑type on @"content" onPeek token‑type onPeek @"content" ... elseOn token‑type elseOnPeek token‑type ... elseOnOthers ... endOn |
on and elseOn consume the next token if it matches the specified type and make it the "current token". onPeek and elseOnPeek set current token to be the next token without consuming it. The current token is stored with any new Cmd node created within the on block. "on" and "onPeek" variations can be mixed & matched - for example on ... elseOnPeek ... or onPeek ... elseOn .... elseOnOthers does not consume the next token or change the current token; it is just the version of "else" for "on".
|
| on/onPeek token‑type additional‑terms ‑> NodeType(...) |
on-produce is a shorthand version of on that allows a list of additional routine calls and token types to be specified after the initial token type. The on performs a matching decision on the first token type and then treats the remaining parse terms as "must-reads". For example, on '(' expression ')' -> Expression(operand) is equivalent to:on '(' expression expression mustConsume(')') produce Expression(operand) endOn |
| while (condition) ... | Single line while loop; separate multiple commands with ;. |
| while (condition) ... endWhile |
Multi-line while loop. |
Expressions result in a value that can be used as a condition for if or while. They can also be used as standalone statements.
| Operator | Description |
|---|---|
| ( expression ) | Standard precedence operator. |
| +, -, *, /, ^ | Add, subtract, multiply, divide, power. |
| ==, !=, <=, >=, <, > | Comparison Operators |
| not | Logical not - if (not hasAnother) .... |
| and, or | Logical AND and OR. if (hasAnother and nextIs(';')) .... |
| Expression | Description |
|---|---|
| routine-name | Call the named routine. The routine returns an integer (default: "0"). |
| call user-routine-name | Call an arbitrarily-named user routine AKA "native routine". The routine is not defined in the .froley file, but rather in the ParserCore class that Froley generates. Define the method by overriding it in the customizable Parser class which extends ParserCore. User routines return an Int. |
| consume("symbol") consume(TOKEN_TYPE) |
Read and discard the next token if it matches the specified type. Evaluates to true on success. |
| consume(@"content") | Read and discard the next token if its string content matches the specified value, regardless of token type. Evaluates to true on success. Only tokens with the [content] attribute have string content. |
| hasAnother | Evaluates to true if another input token is available. |
| nextHasAttribute(attribute-name) | Returns true if the next token has the named attribute - if (nextHasAttribute(content)) .... |
| nextIs("symbol") nextIs(TOKEN_TYPE) |
Evaluates to true if the next available token has the specified type. |
| nextIs(@"content") | Evaluates to true if the string content of the next token matches the specified value regardless of token type. Only tokens with the [content] attribute have string content. |
| read | Reads the next input token. |
- Commands
create XYZandproduce XYZwill create a new extendedCmdnode calledXYZand push it on the stack. - If arguments
create XYZ(alpha,beta)are given, thenXYZis given propertiesalpha:Cmdandbeta:Cmd. Two values are popped off the stack; the topmost value is assigned tobetaand the next value toalphabefore theXYZnode is pushed on the stack. - Specific property types can be declared:
create Routine(name:String,statements:Statements). Each property still pops one node off the stack, but in the case ofStringorInteger(etc.), that node'sto->Stringorto->Int32(etc.) method is called to convert the node into a value. - There are five built-in types:
String,Real,Integer,Character, andLogical. Any other type names are assumed to be the names of extendedCmdtypes. - Node properties can be assigned the value
content:on STRING -> LiteralString(value=content). When this happens, instead of popping off a node from the stack,valuegets its value from the string content of the associated token. Assigningcontentto a property makes it aStringproperty by default unless another built-in type is declared. - Finally, node properties can be assigned an arbitrary backtick-delimited string of native code called a native literal. The content of the string, as native code, is assigned to the property. For example,
create Number(value=`(-1.0).acos`)initializesvaluewith result of the expression(-1.0).acos(the value of π).
From the Simple-Parser scanner example.
--------------------------------------------------------------------------------
parser
--------------------------------------------------------------------------------
- statements
consume_eols
beginList
while (hasAnother)
on "println"
arg_list
create Println(args)
elseOnOthers
expression
endOn
consume_eols
endWhile
produceList Statements
- consume_eols
while (consume(EOL)) noAction
- arg_list
beginList
while (hasAnother and not nextIs(EOL))
expression
endWhile
produceList
- expression
assign
- assign [rightBinary]
on "=" -> Assign
- add_subtract [binary]
on "+" -> Add
on "-" -> Subtract
- multiply_divide [binary]
on "*" -> Multiply
on "/" -> Divide
- power [binary]
on "^" -> Power
- factorial [postUnary]
on "!" -> Factorial
- negate [preUnary]
on "-" -> Negate
- term
on '(' expression ')': return
on IDENTIFIER -> Access(name=content)
on NUMBER -> Number(value=content:Real)
on STRING -> LiteralString(value=content)
syntaxError