ucDefineSyntax
See Also: ucDefine
Defines a syntax construct.
ucDefineSyntax(Definition [, Rank, [, tHandle]])
uCalc does not have any built-in syntax of its own. If you browse through the uCalc header / include file for your compiler (such as uCalcVB.Bas for Visual Basic), you will notice that the syntax constructs for defining functions, operators, variables, or the notation for writing hexadecimal numbers, etc, are all defined using ucDefineSyntax (or the equivalent ucDefine("Syntax: ...")), instead of being hard-coded within the DLL itself. Although you may define syntax constructs with uCalc FMP, the details of how to do it are beyond the scope of this help file. For information on defining syntax constructs, see the help file for uCalc Language Builder.
Example 1: Miscellaneous syntax constructs
This multi-part example shows a series of simple syntax constructs, along with printouts showing what effect they have.
Visual Basic
|
ucDefineSyntax
"This sentence ::= 'Something Else'" Print ucEvalStr("This sentence") ' Returns "Something Else" ucDefineSyntax
"{'&b'}{Number:'[0-1]+'} ::= BaseConvert('{Number}', 2)" Print ucEvalStr("&b101") ' Returns 5 ucDefineSyntax
"Reverse({first}) ::= '{first}'" ucDefineSyntax
"Reverse({first}, {rest}) ::= Reverse({rest}) + ', {first}'" Print ucEvalStr("Reverse(1, 2, 3, 4,
5)") ' Returns "5, 4, 3,
2, 1" ucDefineSyntax
"MySum({x}) ::= {x}" ucDefineSyntax
"MySum({x}, {y}) ::= ({x} + MySum({y}))" Print ucEvalStr("MySum(10, 20, 30, 40,
50)") ' Returns 150 ucDefineSyntax
"CountArgs({x}) ::= 1" ucDefineSyntax
"CountArgs({x}, {y}) ::= ~Eval(1 + CountArgs({y}))" Print ucEvalStr("CountArgs(a+b, 'Hello', -5,
1)") ' Returns 4 ucDefineSyntax
"Average({args}) ::= MySum({args}) / CountArgs({args})" Print ucEvalStr("Average(3, 4, 5,
6)") ' Returns 4.5 ucDefineSyntax
"{a} & {b} ::= '{a}s and {b}s are different'" ucDefineSyntax
"{a} & {a} ::= 'Two {a}s'" Print ucEvalStr("Orange &
Orange") ' Returns "Two
Oranges" Print ucEvalStr("Orange &
Apple") ' Returns
"Oranges and Apples are different" ucDefineSyntax
"{a} & {a} ::= 'Two {a}s are better than one {a}'" Print ucEvalStr("orange &
orange") ' Returns "Two oranges
are better than one orange" |
Note: The order of multiple definitions that are related to each other (such as {a} & {b} and {a} & {a}, or the two definitions for Reverse, etc) is very important.
In Example 1, we defined syntax constructs and tested them using ucEvalStr. Using the same MySum definition from Example 1, we will now highlight the effect of expanding an expression instead. ucEvalStr expands an expression, and then proceeds to evaluate it. ucExpand expands the expression (by performing text substitutions based on the defined syntax constructs), and stops there and returns the expanded result.
Visual Basic
|
ucDefineSyntax
"MySum({x}) ::= {x}" ucDefineSyntax
"MySum({x}, {y}) ::= ({x} + MySum({y}))" Print ucEvalStr("MySum(10, 20, 30, 40,
50)") ' Returns 150 Print ucExpand("MySum(10,
20, 30, 40, 50)") ' Returns (10
+ (20 + (30 + (40 + 50)))) |
The example below returns the nth argument in a list. Here we use ~Eval which evaluates part of an expression in place during the expansion stage, and immediately replaces ~Eval(...) with the result. Similarly, ~Expand expands an expression in place, and also immediately substitutes the result. The final result of ucExpand is as a string, which is not parsed as an expression. If we used ucEvalStr in this example, then once expanded the two lines with the Print statement would then attempt to evaluate the words Second and Fourth, which would raise an error because such words weren't defined. With ucExpand, it doesn't matter much what kind of text the nth argument contains.
Visual Basic
|
ucDefineSyntax
"First([{x}[, {y}]]) ::= {x}" ucDefineSyntax
"Rest([{x} [, {y}]]) ::= {y}" ucDefineSyntax
"nthArg({n}, {list}) ::= nthArg(~Eval({n}-1),
~Expand(Rest({list})))" ucDefineSyntax
"nthArg(1, {list}) ::=
First({list})" Print ucExpand("nthArg(2,
First, Second, Third, Fourth)") ' Returns "Second" Print ucExpand("nthArg(4,
First, Second, Third, Fourth)") ' Returns "Fourth" |
Example 3: Creating an RPN calculator
This example creates a simple RPN (reverse polish notation) calculator.
Visual Basic
|
ucDefineVariable "Left" ucDefineVariable "Right" ucDefineVariable "uc_Stack As Stack" ucDefineFunction "Native: uc_Push(StackName
As Stack, ByHandle Data As AnyType, Index As Long = 0) As Long",
ucAddr(uc_Func_PushData_Stack) ucDefineFunction "Native: uc_PopNum(StackName
As Stack, Index As Long = 0) As Extended", ucAddr(uc_Func_PopNum_Stack) ucDefineSyntax
"pop ::= uc_PopNum(uc_Stack)" ucDefineSyntax
"push({Num}) ::= uc_Push(uc_Stack, {Num})" ucDefineSyntax
"GetOperands ::= SetVar(Right, pop); SetVar(Left, pop)" ucDefineSyntax
"RPN {op} ::= GetOperands; push(Left {op} Right); pop" ucDefineSyntax
"RPN {op} {' '} {other} ::= GetOperands; push(Left {op} Right); RPN
{other}" ucDefineSyntax
"RPN {'[ ]+'} {num:_Number} {other} ::= push({num}); RPN {other}" Print ucEval("RPN 3 4 5 + *") ' Returns 27 Print ucEval("RPN 10 1 - 2 /") ' Returns
4.5 |