module Roger.Alsing { language Common { // Parameterized List rule syntax List(element) = e:element => [e] | es:List(element) e:element => [valuesof(es), e] ; //predefined token Letter = "A".."Z" | "a".."z"; token Digit = "0".."9"; token AlphaNumeric = (Letter | Digit)+; token Printable = "\u0010".."\u00ff"; token SingleQuote = "'"; token DoubleQuote = '"'; // Whitespace token LF = "\u000A"; token CR = "\u000D"; token Space = "\u0020"; @{Classification["Whitespace"]} token Whitespace = CR | Space; } @{CaseSensitive[false]} language Simple { // Charsets token tStringCh1 = Common.Printable - Common.DoubleQuote; token tStringCh2 = Common.Printable - Common.SingleQuote; // Terminals @{Classification["String"]} token tStringLiteral = Common.DoubleQuote tStringCh1* Common.DoubleQuote | Common.SingleQuote tStringCh2* Common.SingleQuote ; token tCommentCh1 = Common.Printable; @{Classification["Comment"]} token tComment = "//" tCommentCh1* ; @{Classification["Identifier"]} token tID = Common.Letter Common.AlphaNumeric*; @{Classification["Numeric"]} token tIntegerLiteral = Common.Digit+; @{Classification["Numeric"]} token tDecimalLiteral = Common.Digit* "." Common.Digit+; @{Classification["Keyword"]} final token tTrueLiteral = "true"; @{Classification["Keyword"]} final token tFalseLiteral = "false"; @{Classification["Keyword"]} final token tPrint = "print"; @{Classification["Keyword"]} final token tWhile = "while"; @{Classification["Keyword"]} final token tIf = "if"; @{Classification["Keyword"]} final token tThen = "then"; @{Classification["Keyword"]} final token tElse = "else"; @{Classification["Keyword"]} final token tEnd = "end"; @{Classification["Keyword"]} final token tDo = "do"; @{Classification["Keyword"]} final token tInput = "input"; @{Classification["Keyword"]} final token tFor = "for"; @{Classification["Keyword"]} final token tNext = "next"; @{Classification["Keyword"]} final token tTo = "to"; @{Classification["Keyword"]} final token tStringType = "string"; @{Classification["Keyword"]} final token tIntegerType = "int"; @{Classification["Keyword"]} final token tBooleanType = "bool"; @{Classification["Keyword"]} final token tDecimalType = "decimal"; @{Classification["Keyword"]} final token tNull = "null"; token LF = Common.LF; //Non terminals syntax Main = sStatements | empty ; syntax sBooleanLiteral = v:tTrueLiteral => "true" | v:tFalseLiteral => "false" ; syntax sStatements = ls:Common.List(sStatement) => StatementList{Statements{ls}} | empty => StatementList{Statements{}} ; syntax sStatement = s:sPrint => s | s:sDeclareVar => s | s:sAssignVar => s | s:sWhile => s | s:sIf => s | s:sFor => s | LF => null ; syntax sPrint = tPrint x:sExpression LF => Print{Expression{x}} ; syntax sAssignVar = i:tID "=" x:sExpression LF => AssignVar{ VariableName{i},Expression{x}} ; syntax sDeclareVar = t:sType i:tID LF => DeclareVar { VariableName{i},Type{t}} | t:sType i:tID "=" x:sExpression LF => DeclareVar { VariableName{i},Type{t},Value{x}} ; syntax sWhile = tWhile x:sExpression tDo LF s:sStatements tEnd => While{ Condition{x},Body{s}} ; syntax sIf = tIf x:sExpression tThen LF s:sStatements e:sElseIf => If{Condition{x},Body{s},Next{e}} ; syntax sElseIf = tElse tIf x:sExpression tThen LF s:sStatements e:sElseIf => ElseIf{Condition{x},Body{s},Next{e}} | e:sElse => e ; syntax sElse = tElse LF es:sStatements sEnd => Else{Body{es}} | e:sEnd => e ; syntax sEnd = tEnd => null ; syntax sFor = tFor i:tID "=" e1:sExpression tTo e2:sExpression LF s:sStatements tNext => For { VariableName{i}, StartExpression{e1}, EndExpression{e2}, Body{s} } | tFor t:sType i:tID "=" e1:sExpression tTo e2:sExpression LF s:sStatements tNext => For { VariableType{t}, VariableName{i}, StartExpression{e1}, EndExpression{e2} , Body{s} } ; syntax sExpression = l:sExpression ">" r:sAddExp => CompareGt{LeftOperand{l},RightOperand{r}} | l:sExpression "<" r:sAddExp => CompareLt{LeftOperand{l},RightOperand{r}} | l:sExpression "<=" r:sAddExp => CompareLtEq{LeftOperand{l},RightOperand{r}} | l:sExpression ">=" r:sAddExp => CompareGtEq{LeftOperand{l},RightOperand{r}} | l:sExpression "==" r:sAddExp => CompareEq{LeftOperand{l},RightOperand{r}} | l:sExpression "<>" r:sAddExp => CompareNotEq{LeftOperand{l},RightOperand{r}} | l:sExpression "!=" r:sAddExp => CompareNotEq{LeftOperand{l},RightOperand{r}} | e:sAddExp => e ; syntax sAddExp = l:sAddExp "+" r:sMultExp => OpAdd{LeftOperand{l},RightOperand{r}} | l:sAddExp "-" r:sMultExp => OpSub{LeftOperand{l},RightOperand{r}} | l:sAddExp "&" r:sMultExp => OpAnd{LeftOperand{l},RightOperand{r}} | e:sMultExp => e ; syntax sMultExp = l:sMultExp "*" r:sUnaryExp => OpMul{LeftOperand{l},RightOperand{r}} | l:sMultExp "/" r:sUnaryExp => OpDiv{LeftOperand{l},RightOperand{r}} | e:sUnaryExp => e ; syntax sUnaryExp = "-" v:sValue => Negate{Expression{v}} | t:sTypeCast => t | v:sValue => v ; syntax sTypeCast = "(" t:sType ")" x:sValue => TypeCast {Type{t},Value{x}} ; syntax sValue = v:tID => Identifier{Name{v}} | v:sBooleanLiteral => BooleanLiteral{RawValue{v}} | v:tStringLiteral => StringLiteral{RawValue{v}} | v:tIntegerLiteral => IntegerLiteral{RawValue{v}} | v:tDecimalLiteral => DecimalLiteral{RawValue{v}} | "(" v:sExpression ")" => v | v:tInput => Input{Foo{"hej"}} | v:tNull => Null{Foo{"hej"}} ; syntax sType = tStringType => Type{RawValue{"System.String"}} | tBooleanType => Type{RawValue{"System.Boolean"}} | tDecimalType => Type{RawValue{"System.Double"}} | tIntegerType => Type{RawValue{"System.Int32"}} ; //whitespace interleave Whitespace = Common.Whitespace | tComment; } }