How to do that exactly is hard to explain since you need a lot of underlying stuff (grammar, AST walker, scope/symbol-table, etc.).
I've written a blog that explains how to create a small programming language. If you read through it and/or download the zip of the last part, you only need to add a couple of things to support user-input. These are the changes you need to make:
In file TL.g:
atom
: Number
| Bool
| Null
| lookup
| Input '(' String? ')' -> ^(Input String?) // added this line
;
Input : 'input'; // added this rule
In file TLTreeWalker.g:
expression returns [TLNode node]
: ^(TERNARY a=expression b=expression c=expression) {node = new TernaryNode($a.node, $b.node, $c.node);}
| ^(In a=expression b=expression) {node = new InNode($a.node, $b.node);}
| ^('||' a=expression b=expression) {node = new OrNode($a.node, $b.node);}
| ^('&&' a=expression b=expression) {node = new AndNode($a.node, $b.node);}
| ^('==' a=expression b=expression) {node = new EqualsNode($a.node, $b.node);}
| ^('!=' a=expression b=expression) {node = new NotEqualsNode($a.node, $b.node);}
| ^('>=' a=expression b=expression) {node = new GTEqualsNode($a.node, $b.node);}
| ^('<=' a=expression b=expression) {node = new LTEqualsNode($a.node, $b.node);}
| ^('>' a=expression b=expression) {node = new GTNode($a.node, $b.node);}
| ^('<' a=expression b=expression) {node = new LTNode($a.node, $b.node);}
| ^('+' a=expression b=expression) {node = new AddNode($a.node, $b.node);}
| ^('-' a=expression b=expression) {node = new SubNode($a.node, $b.node);}
| ^('*' a=expression b=expression) {node = new MulNode($a.node, $b.node);}
| ^('/' a=expression b=expression) {node = new DivNode($a.node, $b.node);}
| ^('%' a=expression b=expression) {node = new ModNode($a.node, $b.node);}
| ^('^' a=expression b=expression) {node = new PowNode($a.node, $b.node);}
| ^(UNARY_MIN a=expression) {node = new UnaryMinusNode($a.node);}
| ^(NEGATE a=expression) {node = new NegateNode($a.node);}
| Number {node = new AtomNode(Double.parseDouble($Number.text));}
| Bool {node = new AtomNode(Boolean.parseBoolean($Bool.text));}
| Null {node = new AtomNode(null);}
| lookup {node = $lookup.node;}
| ^(Input String?) {node = new InputNode($String.text);} // added this line
;
Add the following class:
package tl.tree.functions;
import tl.TLValue;
import tl.tree.TLNode;
import java.io.PrintStream;
import java.util.Scanner;
public class InputNode implements TLNode {
private String prompt;
private PrintStream out;
public InputNode(String p) {
this(p, System.out);
}
public InputNode(String p, PrintStream o) {
prompt = (p == null) ? "" : p;
out = o;
}
@Override
public TLValue evaluate() {
out.println(prompt);
Scanner keyboard = new Scanner(System.in);
if(keyboard.hasNextDouble())
return new TLValue(Double.valueOf(keyboard.nextDouble()));
else if(keyboard.hasNextInt())
return new TLValue(Integer.valueOf(keyboard.nextInt()));
else if(keyboard.hasNextBoolean())
return new TLValue(Boolean.valueOf(keyboard.nextBoolean()));
else
return new TLValue(keyboard.nextLine().trim()); // else it's a plain string
}
}
And if you now evaluate the input:
a = 10;
b = input("Enter a number: ");
println(a + b);
you will be prompted with the message Enter a number:
and this number is then added to a
and will be printed to the console.