453 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ANTLR
		
	
	
	
	
	
			
		
		
	
	
			453 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ANTLR
		
	
	
	
	
	
grammar plsm;
 | 
						|
 | 
						|
@parser::header {
 | 
						|
#include "AST/AST.h"
 | 
						|
#include "Utils.h"
 | 
						|
#include <memory>
 | 
						|
#include <boost/json.hpp>
 | 
						|
#include <boost/algorithm/string.hpp>
 | 
						|
 | 
						|
using namespace plsm::utils;
 | 
						|
using namespace plsm::ast;
 | 
						|
}
 | 
						|
 | 
						|
@parser::members {
 | 
						|
  std::string filename, sourceText;
 | 
						|
 | 
						|
  void setFileName(const std::string &filename) { this->filename = filename; }
 | 
						|
  void setSourceText(const std::string &sourceText) { this->sourceText = sourceText; }
 | 
						|
 | 
						|
  inline SourceRange getSourceRange(antlr4::ParserRuleContext *ctx) {
 | 
						|
    auto start = ctx->start;
 | 
						|
    auto stop = getCurrentToken();
 | 
						|
 | 
						|
    auto startPos = std::pair<size_t, size_t>(start->getLine(),
 | 
						|
                                              start->getCharPositionInLine());
 | 
						|
    auto stopPos = std::pair<size_t, size_t>(stop->getLine(),
 | 
						|
                                             stop->getCharPositionInLine());
 | 
						|
 | 
						|
    auto text = sourceText.substr(
 | 
						|
        start->getStartIndex(), stop->getStartIndex() - start->getStartIndex());
 | 
						|
    text = boost::trim_copy(text);
 | 
						|
 | 
						|
//     std::cout << "text: `" << text << "`" << std::endl;
 | 
						|
 | 
						|
    return SourceRange(filename, text, startPos, stopPos);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
module
 | 
						|
	returns[std::unique_ptr<Module> ast]: (stmts += topLevelStmt)* EOF {
 | 
						|
          std::vector<std::unique_ptr<Stmt>> stmts;
 | 
						|
          for (auto &stmt : $ctx->stmts) {
 | 
						|
               stmts.push_back(std::move(stmt->ast));
 | 
						|
          }
 | 
						|
 | 
						|
          $ast = std::make_unique<Module>(getSourceRange($ctx), "default", std::vector<std::unique_ptr<Import>>(), std::move(stmts));
 | 
						|
     };
 | 
						|
 | 
						|
topLevelStmt
 | 
						|
	returns[std::unique_ptr<Stmt> ast]:
 | 
						|
	varDecl {
 | 
						|
          $ast = ptrcast<Stmt>($ctx->varDecl()->ast);
 | 
						|
     }
 | 
						|
	| fnDecl {
 | 
						|
          $ast = ptrcast<Stmt>($ctx->fnDecl()->ast);
 | 
						|
     };
 | 
						|
 | 
						|
block
 | 
						|
	returns[std::unique_ptr<Block> ast]:
 | 
						|
	(stmts += stmt)* {
 | 
						|
          std::vector<std::unique_ptr<Stmt>> stmts;
 | 
						|
          for (auto &stmt : $ctx->stmts) {
 | 
						|
               stmts.push_back(std::move(stmt->ast));
 | 
						|
          }
 | 
						|
 | 
						|
          $ast = std::make_unique<Block>(getSourceRange($ctx), std::move(stmts));
 | 
						|
     };
 | 
						|
 | 
						|
singleStmtBlock
 | 
						|
	returns[std::unique_ptr<Block> ast]:
 | 
						|
	stmt {
 | 
						|
          std::vector<std::unique_ptr<Stmt>> stmts;
 | 
						|
          stmts.push_back(std::move($ctx->stmt()->ast));
 | 
						|
          $ast = std::make_unique<Block>(getSourceRange($ctx), std::move(stmts));
 | 
						|
     };
 | 
						|
 | 
						|
stmt
 | 
						|
	returns[std::unique_ptr<Stmt> ast]:
 | 
						|
	exprStmt {
 | 
						|
          $ast = ptrcast<Stmt>($ctx->exprStmt()->ast);
 | 
						|
     }
 | 
						|
	| varDecl {
 | 
						|
          $ast = ptrcast<Stmt>($ctx->varDecl()->ast);
 | 
						|
     }
 | 
						|
	| retStmt {
 | 
						|
          $ast = ptrcast<Stmt>($ctx->retStmt()->ast);
 | 
						|
     }
 | 
						|
	| assignStmt {
 | 
						|
          $ast = ptrcast<Stmt>($ctx->assignStmt()->ast);
 | 
						|
     }
 | 
						|
	| implDeclAssignStmt {
 | 
						|
          $ast = ptrcast<Stmt>($ctx->implDeclAssignStmt()->ast);
 | 
						|
     }
 | 
						|
	| ifStmt {
 | 
						|
          $ast = ptrcast<Stmt>($ctx->ifStmt()->ast);
 | 
						|
     }
 | 
						|
	| whileStmt {
 | 
						|
          $ast = ptrcast<Stmt>($ctx->whileStmt()->ast);
 | 
						|
     }
 | 
						|
	| inlineAsm {
 | 
						|
          $ast = ptrcast<Stmt>($ctx->inlineAsm()->ast);
 | 
						|
     };
 | 
						|
 | 
						|
inlineAsm
 | 
						|
	returns[std::unique_ptr<InlineAsm> ast]:
 | 
						|
	'inline' 'asm' '(' (inlineAsmCode += string)+ (
 | 
						|
		':' (
 | 
						|
			outputs += inlineAsmConstraint (
 | 
						|
				',' outputs += inlineAsmConstraint
 | 
						|
			)*
 | 
						|
		)?
 | 
						|
	)? (
 | 
						|
		':' (
 | 
						|
			inputs += inlineAsmConstraint (
 | 
						|
				',' inputs += inlineAsmConstraint
 | 
						|
			)*
 | 
						|
		)?
 | 
						|
	)? (':' (clobbers += string ( ',' clobbers += string)*)?)? ')' ';' {
 | 
						|
          std::string code = "";
 | 
						|
          for (auto &asmCode : $ctx->inlineAsmCode) {
 | 
						|
               code += asmCode->value;
 | 
						|
               code += ";";
 | 
						|
          }
 | 
						|
          code.pop_back();
 | 
						|
 | 
						|
          std::vector<std::unique_ptr<InlineAsmConstraint>> outputs;
 | 
						|
          for (auto &output : $ctx->outputs) {
 | 
						|
               outputs.push_back(std::move(output->ast));
 | 
						|
          }
 | 
						|
 | 
						|
          std::vector<std::unique_ptr<InlineAsmConstraint>> inputs;
 | 
						|
          for (auto &input : $ctx->inputs) {
 | 
						|
               inputs.push_back(std::move(input->ast));
 | 
						|
          }
 | 
						|
 | 
						|
          std::vector<std::string> clobbers;
 | 
						|
          for (auto &clobber : $ctx->clobbers) {
 | 
						|
               clobbers.push_back(clobber->value);
 | 
						|
          }
 | 
						|
 | 
						|
          $ast = std::make_unique<InlineAsm>(
 | 
						|
               getSourceRange($ctx), code, std::move(outputs), std::move(inputs), clobbers);
 | 
						|
    };
 | 
						|
 | 
						|
inlineAsmConstraint
 | 
						|
	returns[std::unique_ptr<InlineAsmConstraint> ast]:
 | 
						|
	string '(' expr ')' {
 | 
						|
        auto constraint = $ctx->string()->value;
 | 
						|
        $ast = std::make_unique<InlineAsmConstraint>(getSourceRange($ctx), constraint, std::move($ctx->expr()->ast));
 | 
						|
    };
 | 
						|
 | 
						|
inlineAsmLvalueConstraint
 | 
						|
	returns[std::unique_ptr<InlineAsmConstraint> ast]:
 | 
						|
	string '(' lvalue ')' {
 | 
						|
        auto constraint = $ctx->string()->value;
 | 
						|
        $ast = std::make_unique<InlineAsmConstraint>(getSourceRange($ctx), constraint, std::move($ctx->lvalue()->ast));
 | 
						|
    };
 | 
						|
 | 
						|
whileStmt
 | 
						|
	returns[std::unique_ptr<WhileStmt> ast]:
 | 
						|
	'while' '(' condition = expr ')' (
 | 
						|
		'{' block '}'
 | 
						|
		| singleStmtBlock
 | 
						|
	) {
 | 
						|
          std::unique_ptr<Block> body;
 | 
						|
          if ($ctx->block()) body = std::move($ctx->block()->ast);
 | 
						|
          else body = std::move($ctx->singleStmtBlock()->ast);
 | 
						|
 | 
						|
          $ast = std::make_unique<WhileStmt>(getSourceRange($ctx), std::move($ctx->condition->ast), std::move(body));
 | 
						|
     };
 | 
						|
 | 
						|
ifStmt
 | 
						|
	returns[std::unique_ptr<IfStmt> ast]:
 | 
						|
	'if' '(' condition = expr ')' (
 | 
						|
		'{' ifBlock = block '}'
 | 
						|
		| ifSingleBlock = singleStmtBlock
 | 
						|
	) (
 | 
						|
		'else' (
 | 
						|
			'{' elseBlock = block '}'
 | 
						|
			| elseSingleBlock = singleStmtBlock
 | 
						|
		)
 | 
						|
	)? {
 | 
						|
          std::unique_ptr<Block> ifBody;
 | 
						|
          if ($ctx->ifBlock) ifBody = std::move($ctx->ifBlock->ast);
 | 
						|
          else ifBody = std::move($ctx->ifSingleBlock->ast);
 | 
						|
 | 
						|
          std::unique_ptr<Block> elseBody;
 | 
						|
          if ($ctx->elseBlock) elseBody = std::move($ctx->elseBlock->ast);
 | 
						|
          else if ($ctx->elseSingleBlock) elseBody = std::move($ctx->elseSingleBlock->ast);
 | 
						|
          else elseBody = std::make_unique<Block>(SourceRange::unknown(), std::vector<std::unique_ptr<Stmt>>());
 | 
						|
 | 
						|
          $ast = std::make_unique<IfStmt>(getSourceRange($ctx), std::move($ctx->condition->ast), std::move(ifBody), std::move(elseBody));
 | 
						|
     };
 | 
						|
 | 
						|
implDeclAssignStmt
 | 
						|
	returns[std::unique_ptr<Stmt> ast]:
 | 
						|
	IDENTIFIER ':=' expr {
 | 
						|
          // TODO
 | 
						|
     };
 | 
						|
 | 
						|
assignStmt
 | 
						|
	returns[std::unique_ptr<AssignStmt> ast]:
 | 
						|
	lval = lvalue '=' rval = expr ';' {
 | 
						|
          $ast = std::make_unique<AssignStmt>(getSourceRange($ctx), std::move($ctx->lval->ast), std::move($ctx->rval->ast));
 | 
						|
     };
 | 
						|
 | 
						|
lvalue
 | 
						|
	returns[std::unique_ptr<Expr> ast]:
 | 
						|
	identifier {
 | 
						|
          $ast = ptrcast<Expr>($ctx->identifier()->ast);
 | 
						|
     };
 | 
						|
 | 
						|
retStmt
 | 
						|
	returns[std::unique_ptr<RetStmt> ast]:
 | 
						|
	'ret' expr ';' {
 | 
						|
          $ast = std::make_unique<RetStmt>(getSourceRange($ctx), std::move($ctx->expr()->ast));
 | 
						|
     };
 | 
						|
 | 
						|
fnDecl
 | 
						|
	returns[std::unique_ptr<FnDecl> ast]:
 | 
						|
	'fun' name = IDENTIFIER '(' (
 | 
						|
		params += fnParam (',' params += fnParam)*
 | 
						|
	)? ')' typeName '{' block '}' {
 | 
						|
          auto name = $ctx->name->getText();
 | 
						|
 | 
						|
          std::vector<std::unique_ptr<FnParam>> params;
 | 
						|
          for (auto ¶m : $ctx->params) {
 | 
						|
               params.push_back(std::move(param->ast));
 | 
						|
          }
 | 
						|
 | 
						|
          $ast = std::make_unique<FnDecl>(getSourceRange($ctx), name, std::move(params), std::move($ctx->typeName()->ast), std::move($ctx->block()->ast));
 | 
						|
     };
 | 
						|
 | 
						|
fnParam
 | 
						|
	returns[std::unique_ptr<FnParam> ast]:
 | 
						|
	IDENTIFIER ':' typeName {
 | 
						|
          $ast = std::make_unique<FnParam>(getSourceRange($ctx), $ctx->IDENTIFIER()->getText(), std::move($ctx->typeName()->ast));
 | 
						|
     };
 | 
						|
 | 
						|
varDecl
 | 
						|
	returns[std::unique_ptr<VarDecl> ast]:
 | 
						|
	'var' IDENTIFIER ':' typeName ';' {
 | 
						|
          auto name = $ctx->IDENTIFIER()->getText();
 | 
						|
          $ast = std::make_unique<VarDecl>(getSourceRange($ctx), name, std::move($ctx->typeName()->ast));
 | 
						|
     };
 | 
						|
 | 
						|
exprStmt
 | 
						|
	returns[std::unique_ptr<ExprStmt> ast]:
 | 
						|
	expr ';' {
 | 
						|
          $ast = std::make_unique<ExprStmt>(getSourceRange($ctx), std::move($ctx->expr()->ast));
 | 
						|
     };
 | 
						|
 | 
						|
expr
 | 
						|
	returns[std::unique_ptr<Expr> ast]:
 | 
						|
	value = binaryExpr {
 | 
						|
          $ast = std::move($ctx->value->ast);
 | 
						|
     };
 | 
						|
 | 
						|
binaryExpr
 | 
						|
	returns[std::unique_ptr<Expr> ast]:
 | 
						|
	value = unaryExpr {
 | 
						|
          $ast = std::move($ctx->value->ast);
 | 
						|
     }
 | 
						|
	| lhs = binaryExpr op = ('*' | '/' | '%') rhs = binaryExpr {
 | 
						|
          auto opText = $ctx->op->getText();
 | 
						|
 | 
						|
          BinOp op;
 | 
						|
          if (opText == "*") op = BinOp::MUL;
 | 
						|
          if (opText == "/") op = BinOp::DIV;
 | 
						|
          if (opText == "%") op = BinOp::MOD;
 | 
						|
 | 
						|
          auto binExpr = std::make_unique<BinExpr>(getSourceRange($ctx), op, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast));
 | 
						|
          $ast = ptrcast<Expr>(binExpr);
 | 
						|
     }
 | 
						|
	| lhs = binaryExpr op = ('+' | '-') rhs = binaryExpr {
 | 
						|
          auto opText = $ctx->op->getText();
 | 
						|
 | 
						|
          BinOp op;
 | 
						|
          if (opText == "+") op = BinOp::ADD;
 | 
						|
          if (opText == "-") op = BinOp::SUB;
 | 
						|
 | 
						|
          auto binExpr = std::make_unique<BinExpr>(getSourceRange($ctx), op, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast));
 | 
						|
          $ast = ptrcast<Expr>(binExpr);
 | 
						|
     }
 | 
						|
	| lhs = binaryExpr op = (
 | 
						|
		'=='
 | 
						|
		| '!='
 | 
						|
		| '>='
 | 
						|
		| '<='
 | 
						|
		| '>'
 | 
						|
		| '<'
 | 
						|
	) rhs = binaryExpr {
 | 
						|
          auto opText = $ctx->op->getText();
 | 
						|
 | 
						|
          BinOp op;
 | 
						|
          if (opText == "==") op = BinOp::EQ;
 | 
						|
          if (opText == "!=") op = BinOp::NE;
 | 
						|
          if (opText == ">=") op = BinOp::GE;
 | 
						|
          if (opText == "<=") op = BinOp::LE;
 | 
						|
          if (opText == ">") op = BinOp::GT;
 | 
						|
          if (opText == "<") op = BinOp::LT;
 | 
						|
 | 
						|
          auto binExpr = std::make_unique<BinExpr>(getSourceRange($ctx), op, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast));
 | 
						|
          $ast = ptrcast<Expr>(binExpr);
 | 
						|
     }
 | 
						|
	| lhs = binaryExpr '&&' rhs = binaryExpr {
 | 
						|
          auto binExpr = std::make_unique<BinExpr>(getSourceRange($ctx), BinOp::AND, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast));
 | 
						|
          $ast = ptrcast<Expr>(binExpr);
 | 
						|
     }
 | 
						|
	| lhs = binaryExpr '||' rhs = binaryExpr {
 | 
						|
          auto binExpr = std::make_unique<BinExpr>(getSourceRange($ctx), BinOp::OR, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast));
 | 
						|
          $ast = ptrcast<Expr>(binExpr);
 | 
						|
     };
 | 
						|
 | 
						|
unaryExpr
 | 
						|
	returns[std::unique_ptr<Expr> ast]:
 | 
						|
	factorExpr {
 | 
						|
          $ast = ptrcast<Expr>($ctx->factorExpr()->ast);
 | 
						|
     }
 | 
						|
	| functionCall {
 | 
						|
          $ast = ptrcast<Expr>($ctx->functionCall()->ast);
 | 
						|
     }
 | 
						|
	| unaryExpr 'as' typeName {
 | 
						|
          auto castExpr = std::make_unique<CastExpr>(getSourceRange($ctx), std::move($ctx->unaryExpr()->ast), std::move($ctx->typeName()->ast));
 | 
						|
          $ast = ptrcast<Expr>(castExpr);
 | 
						|
     }
 | 
						|
	| '!' unaryExpr {
 | 
						|
          auto unExpr = std::make_unique<UnExpr>(getSourceRange($ctx), UnOp::NOT, std::move($ctx->unaryExpr()->ast));
 | 
						|
          $ast = ptrcast<Expr>(unExpr);
 | 
						|
     }
 | 
						|
	| '+' unaryExpr {
 | 
						|
          auto unExpr = std::make_unique<UnExpr>(getSourceRange($ctx), UnOp::POS, std::move($ctx->unaryExpr()->ast));
 | 
						|
          $ast = ptrcast<Expr>(unExpr);
 | 
						|
     }
 | 
						|
	| '-' unaryExpr {
 | 
						|
          auto unExpr = std::make_unique<UnExpr>(getSourceRange($ctx), UnOp::NEG, std::move($ctx->unaryExpr()->ast));
 | 
						|
          $ast = ptrcast<Expr>(unExpr);
 | 
						|
     };
 | 
						|
 | 
						|
factorExpr
 | 
						|
	returns[std::unique_ptr<Expr> ast]:
 | 
						|
	IDENTIFIER {
 | 
						|
          auto id = std::make_unique<Identifier>(getSourceRange($ctx), $ctx->IDENTIFIER()->getText());
 | 
						|
          $ast = ptrcast<Expr>(id);
 | 
						|
     }
 | 
						|
	| INT {
 | 
						|
          auto text = $ctx->INT()->getText();
 | 
						|
 | 
						|
          int64_t value;
 | 
						|
 | 
						|
          if (!text.rfind("0x", 0))
 | 
						|
               value = std::strtol(text.substr(2).data(), NULL, 16);
 | 
						|
 | 
						|
          else if (!text.rfind("0o", 0))
 | 
						|
               value = std::strtol(text.substr(2).data(), NULL, 8);
 | 
						|
 | 
						|
          else if (!text.rfind("0b", 0))
 | 
						|
               value = std::strtol(text.substr(2).data(), NULL, 2);
 | 
						|
 | 
						|
          else
 | 
						|
               value = std::strtol(text.data(), NULL, 10);
 | 
						|
 | 
						|
          auto val = std::make_unique<IntValue>(getSourceRange($ctx), value);
 | 
						|
          $ast = ptrcast<Expr>(val);
 | 
						|
     }
 | 
						|
	| FLOAT {
 | 
						|
          auto text = $ctx->FLOAT()->getText();
 | 
						|
 | 
						|
          if (text.at(text.size() - 1) == '.')
 | 
						|
               text += "0";
 | 
						|
          if (text.at(0) == '0')
 | 
						|
               text = "0" + text;
 | 
						|
 | 
						|
          double value = std::strtod(text.data(), NULL);
 | 
						|
          auto val = std::make_unique<FloatValue>(getSourceRange($ctx), value);
 | 
						|
          $ast = ptrcast<Expr>(val);
 | 
						|
     }
 | 
						|
	| BOOL {
 | 
						|
          auto text = $ctx->BOOL()->getText();
 | 
						|
          auto val = std::make_unique<IntValue>(getSourceRange($ctx), text == "true" ? 1 : 0);
 | 
						|
          $ast = ptrcast<Expr>(val);
 | 
						|
     }
 | 
						|
	| lambdaExpr {
 | 
						|
          $ast = ptrcast<Expr>($ctx->lambdaExpr()->ast);
 | 
						|
     }
 | 
						|
	| string {
 | 
						|
          $ast = std::unique_ptr<Expr>((Expr *) new StringValue(getSourceRange($ctx), $ctx->string()->value));
 | 
						|
     }
 | 
						|
	| '(' expr ')' {
 | 
						|
          $ast = std::move($ctx->expr()->ast);
 | 
						|
     };
 | 
						|
 | 
						|
functionCall
 | 
						|
	returns[std::unique_ptr<CallExpr> ast]:
 | 
						|
	callee = factorExpr '(' (args += expr (',' args += expr)*)? ')' {
 | 
						|
          std::vector<std::unique_ptr<Expr>> args;
 | 
						|
          for (auto &arg : $ctx->args) {
 | 
						|
               args.push_back(std::move(arg->ast));
 | 
						|
          }
 | 
						|
 | 
						|
          $ast = std::make_unique<CallExpr>(getSourceRange($ctx), std::move($ctx->callee->ast), std::move(args));
 | 
						|
     };
 | 
						|
 | 
						|
lambdaExpr
 | 
						|
	returns[std::unique_ptr<LambdaExpr> ast]:
 | 
						|
	'@' '(' (params += fnParam (',' params += fnParam)*)? ')' typeName '{' block '}' {
 | 
						|
          std::vector<std::unique_ptr<FnParam>> params;
 | 
						|
          for (auto ¶m : $ctx->params) {
 | 
						|
               params.push_back(std::move(param->ast));
 | 
						|
          }
 | 
						|
 | 
						|
          $ast = std::make_unique<LambdaExpr>(getSourceRange($ctx), std::move(params), std::move($ctx->typeName()->ast), std::move($ctx->block()->ast));
 | 
						|
     };
 | 
						|
 | 
						|
typeName
 | 
						|
	returns[std::unique_ptr<TypeName> ast]:
 | 
						|
	IDENTIFIER {
 | 
						|
          auto text = $ctx->IDENTIFIER()->getText();
 | 
						|
          auto named = std::make_unique<NamedTypeName>(getSourceRange($ctx), text);
 | 
						|
          $ast = ptrcast<TypeName>(named);
 | 
						|
     }
 | 
						|
	| '&' typeName {
 | 
						|
          auto typeName = std::move($ctx->typeName()->ast);
 | 
						|
          auto ptr = std::make_unique<PointerTypeName>(getSourceRange($ctx), std::move(typeName));
 | 
						|
          $ast = ptrcast<TypeName>(ptr);
 | 
						|
     };
 | 
						|
 | 
						|
string
 | 
						|
	returns[std::string value]:
 | 
						|
	STRING {
 | 
						|
          auto encoded = $ctx->STRING()->getText();
 | 
						|
          auto decoded = boost::json::parse(encoded);
 | 
						|
          $value = decoded.as_string();
 | 
						|
     };
 | 
						|
 | 
						|
identifier
 | 
						|
	returns[std::unique_ptr<Identifier> ast]:
 | 
						|
	IDENTIFIER {
 | 
						|
          $ast = std::make_unique<Identifier>(getSourceRange($ctx), $ctx->IDENTIFIER()->getText());
 | 
						|
     };
 | 
						|
 | 
						|
STRING: '"' (ESC | ~["\\\r\n])* '"';
 | 
						|
fragment ESC: '\\' (["\\/bfnrt] | 'u' HEX HEX HEX HEX);
 | 
						|
fragment HEX: [0-9a-fA-F];
 | 
						|
 | 
						|
INT: [0-9]+ | '0x' [0-9a-fA-F]+ | '0o' [0-7]+ | '0b' [01]+;
 | 
						|
FLOAT: [0-9]+ '.' | [0-9]* '.' [0-9]+;
 | 
						|
BOOL: 'true' | 'false';
 | 
						|
 | 
						|
IDENTIFIER: [a-zA-Z_] [a-zA-Z0-9_]*;
 | 
						|
 | 
						|
WHITESPACE: [ \r\n\t]+ -> skip;
 | 
						|
COMMENT: (('//' ~( '\r' | '\n')*) | ('/*' .*? '*/')) -> skip; |