Skip to content

Commit bd346ad

Browse files
committed
minor parser improvements. allow > as output prefix.
1 parent 6414dfc commit bd346ad

File tree

3 files changed

+40
-23
lines changed

3 files changed

+40
-23
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ Supported. This is the native format for `dmnmd`.
117117

118118
ASCII has its limitations. In graphical decision tables, output columns are separated from input columns by a double bar; most GUI implementations use colour and other formatting to distinguish input, output, and annotation columns. In `dmnmd` syntax, output columns are optionally labeled with an `(out)`; annotation columns are prefixed with a `#`. By default, if the columns are unlabeled, the rightmost column will be taken to be the output, and columns to the left will be taken to be inputs. (Leaving out annotation columns.)
119119

120+
You can also prefix output columns with a `>` character.
121+
120122
Columns are optionally typed using a colon. You will see `Column Name : String`, `Column Name : Number`, and `Column Name : Boolean`. If you omit the type definition, `dmnmd` will attempt to infer the type.
121123

122124
In some decision tables, the input and outputs are enumerated in a sort of sub-header row. The order matters.
@@ -131,7 +133,7 @@ For hit policy "O", the order of results in the output is determined by the orde
131133

132134
The column enums are giving in a subhead row between the top row and body data row "1".
133135

134-
| O | Age | Risk Category | Debt Review :Boolean | Routing (out) | Review level (out) | Reason (out) |
136+
| O | Age | Risk Category | Debt Review :Boolean | > Routing | > Review level | Reason (out) |
135137
|---|-----|-------------------|----------------------|------------------------|------------------------|-----------------------------|
136138
| | | LOW, MEDIUM, HIGH | | DECLINE, REFER, ACCEPT | LEVEL 2, LEVEL 1, NONE | |
137139
| 1 | - | - | - | ACCEPT | NONE | Acceptable |

languages/haskell/src/DMN/ParseFEEL.hs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Control.Applicative hiding (many, some)
77
import Text.Megaparsec
88
import Text.Megaparsec.Char
99
import Data.Text (Text)
10+
import Data.Char (isAlphaNum)
1011
import qualified Data.Text as T
1112
import DMN.Types
1213
import DMN.ParsingUtils
@@ -17,11 +18,15 @@ import Debug.Trace
1718
-- let's allow spaces in variable names. what could possibly go wrong?
1819
parseVarname :: Parser Text
1920
parseVarname = do
20-
input <- T.take 40 <$> lookAhead takeRest
21-
-- traceM $ "parseVarname: input: " ++ T.unpack input
21+
-- input <- T.take 40 <$> lookAhead takeRest; traceM $ "parseVarname: input: " ++ T.unpack input
2222
firstLetter <- letterChar
23-
remainder <- some (choice [ alphaNumChar, char '_', char ' ' ])
24-
return $ T.strip $ T.append (T.singleton firstLetter) (T.pack remainder)
23+
remainder <- takeWhileP (Just "legal identifier character, including spaces")
24+
(\c -> isAlphaNum c || c == '\t'
25+
|| c == ' ' || c == '\x00A0' -- nonbreaking space
26+
|| c == '_' || c == '_' )
27+
28+
-- we should now have run up against either eol, |, (, or :
29+
return $ T.strip $ T.cons firstLetter remainder
2530

2631

2732
parseFNumFunction :: Parser FNumFunction

languages/haskell/src/DMN/ParseTable.hs

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,40 +48,50 @@ pipeSeparator = try $ Mega.label "pipeSeparator" $ skipHorizontalSpace >> "|" >
4848
getpipeSeparator :: Parser Text
4949
getpipeSeparator = skipHorizontalSpace *> "|" <* skipHorizontalSpace
5050

51+
-- | parse column header.
52+
-- (//|#|>|<) *([a-zA-Z0-9_ ]+?( *: *[a-z]+) *
5153
parseColHeader :: Parser ColHeader
5254
parseColHeader = do
53-
mylabel_pre <- parseLabelPre <* skipHorizontalSpace <?> "mylabel_pre"
54-
myvarname <- parseVarname <?> "parseVarname"
55+
mylabel_pre <- parseLabelPre <?> "pre-label"
56+
myvarname <- parseVarname <?> "variable name"
5557
doTrace $ "parseColHeader: done with parseVarname, got: \"" ++ T.unpack myvarname ++ "\""
56-
mytype <- parseTypeDecl <?> "parseTypeDecl"
57-
mylabel_post <- skipHorizontalSpace *> parseLabelPost <?> "parseLabelPost"
58-
return $ DTCH (mkHeaderLabel mylabel_pre mylabel_post) (T.unpack myvarname) mytype Nothing
58+
mytype <- parseTypeDecl <?> "type declaration"
59+
mylabel_post <- skipHorizontalSpace *> parseLabelPost <?> "post-label (in/out/comment)"
60+
return ( DTCH
61+
(mkHeaderLabel mylabel_pre mylabel_post)
62+
(T.unpack myvarname)
63+
mytype Nothing )
5964

60-
parseTypeDecl :: Parser (Maybe DMNType) -- Nothing means it's up to some later code to infer the type. Usually it gets treated just like a String.
61-
parseTypeDecl = Mega.optional $ do
62-
skipHorizontalSpace >> ":" >> skipHorizontalSpace
63-
parseType
65+
-- | Nothing means it's up to some later code to infer the type. Usually it gets treated just like a String.
66+
parseTypeDecl :: Parser (Maybe DMNType)
67+
parseTypeDecl = Mega.optional $ lexeme ":" *> parseType
6468

65-
parseType :: Parser DMNType
66-
parseType =
67-
DMN_List <$> ("[" *> parseType <* "]" <?> "inside list")
68-
<|>
69-
((("String" >> return (DMN_String)) <?> "string type") <|>
70-
(("Number" >> return (DMN_Number)) <?> "number type") <|>
71-
(("Boolean" >> return (DMN_Boolean)) <?> "boolean type") ) -- need to check what the official DMN names are for these
69+
lexeme :: Parser a -> Parser a
70+
lexeme x = x <* skipHorizontalSpace
7271

72+
parseType :: Parser DMNType
73+
parseType
74+
= (DMN_List <$> (lexeme "[" *> parseType <* lexeme "]") <?> "inside list")
75+
<|> (DMN_String <$ lexeme "String" <?> "string type")
76+
<|> (DMN_Number <$ lexeme "Number" <?> "number type")
77+
<|> (DMN_Boolean <$ lexeme "Boolean" <?> "boolean type")
78+
-- need to check what the official DMN names are for these
79+
80+
mkHeaderLabel :: Maybe Text -> Maybe Text -> DTCH_Label
7381
mkHeaderLabel (Just "//") _ = DTCH_Comment
7482
mkHeaderLabel (Just "#" ) _ = DTCH_Comment
83+
mkHeaderLabel (Just "<" ) _ = DTCH_In
84+
mkHeaderLabel (Just ">" ) _ = DTCH_Out
7585
mkHeaderLabel _ (Just "(comment)") = DTCH_Comment
7686
mkHeaderLabel _ (Just "(out)") = DTCH_Out
7787
mkHeaderLabel _ (Just "(in)") = DTCH_In
7888
mkHeaderLabel _ Nothing = DTCH_In
7989

8090
parseLabelPre :: Parser (Maybe Text)
81-
parseLabelPre = Mega.optional ("//" <|> "#")
91+
parseLabelPre = Mega.optional $ lexeme ("//" <|> "#" <|> "<" <|> ">")
8292

8393
parseLabelPost :: Parser (Maybe Text)
84-
parseLabelPost = Mega.optional ("(in)" <|> "(out)" <|> "(comment)")
94+
parseLabelPost = Mega.optional $ lexeme ("(in)" <|> "(out)" <|> "(comment)")
8595

8696
parseHitPolicy :: Parser HitPolicy
8797
parseHitPolicy =

0 commit comments

Comments
 (0)