Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I need to parse a "commands" where each command is is a string of letters and numbers: a34b56c32alpha

Does xparse have any way to deal with the numbers?

I would like to specify it with something like { 'a' n 'b' n 'c' n m }

where n would be a number.

Basically this is to save having to use unnecessary delimiters (it's already more complex and I can't use ,).

I'm new to xparse and didn't see anything in the docs about being able to parse numbers.

\documentclass[11pt]{book} % use larger type; default would be 10pt
%\documentclass[11pt,a4paper,oneside]{report}

\usepackage{pgffor}
\usepackage{xparse}
\begin{document}

\DeclareDocumentCommand{\Dotparse}{o m}
{
#1
}

% Passes each value in the array to an xparse command.
\def\Dots#1
{
    \foreach \n in {#1}{
        \Dotparse{\n}
}}

\Dots{[3]f4s3,f12s5,s2f14,[5]e,f,g,1,2,3,4,5,6,7}


\end{document}

This code does not parse the optional commands

The above should display 3, , , 5, , , , .... but I get No Value for all. not sure what is going on.

In any case, what I want the output to be is for

\Dots{[3]f4s3,f12s5,s2f14,[5]e,f,g,1,2,3,4,5,6,7}

to parse into

[3](f + 4), s + 3, f + 12, s + 5, ...

where the the + does not mean addition BUT simply is a separator.

So #1 = 3, #2 = f, #3 = s, #4 = 4

(note, don't get confused by the array, it is irrelevant. I iterate over it and THEN pass the element to the xparser which is all I am concerned about now... e.g., I want to parse [3]f4s3 into it's it's tokens where f4s3 is actually 4 tokens. f43s35 would still be 4 since for my purposes)

for example, which such a parser I could write x353.43y32.435z345.3cgreen to represent a 3d point with color. Obviously it looks more confusing than using commands or = signs but it is very compact which is what I'm after.

share|improve this question
    
This looks well outside of the scope of xparse, which is meant to define document command syntax in an ordered way. Complex parsing of structured input is not something we've aimed for, or would necessarily encourage (although the latter of course depends on the context). –  Joseph Wright Mar 16 '12 at 11:54
    
It seems xparse could be quite powerful if it allowed one to recursively define parsers(commands) and expanded it's specification abilities. It could essentially be used to define grammar parsers and possibly make the latex world much better. Basically instead of having to create the recursion manually it could be part of the specification. Of course things get more complex but that's what makes things interesting... –  Uiy Mar 16 '12 at 12:01
2  
It's unclear what's the input and what's the desired output. –  egreg Mar 16 '12 at 12:18
    
What's the relation between x353.43y32.435z345.3cgreen and something like [3]f4s3,f12s5,s2f14,[5]e,f,g,1,2,3,4,5,6,7? It's quite difficult to understand. I would specify (354.43,32.435,345.3,green) which is clearer and more easily parsed or used. –  egreg Mar 16 '12 at 12:44
    
I give up!!!!!! –  Uiy Mar 16 '12 at 12:50
add comment

1 Answer

up vote 1 down vote accepted

LPeg is the way to go when trying to parse relatively complex strings. It at first seems a bit complex but actually is not. Here is a very short tutorial from what I learned:

-- These are alias for lpeg's build in pattern matching functions
local P,C,V,Ct = lpeg.P, lpeg.C, lpeg.V, lpeg.Ct

-- This is lua dictionary that represents a grammar in lpeg notation
local p = {
    "S";  -- Start symbol
    S = V"Rule1" * V"Rule2",
    Rule1 =  P"a" * P"b",
    Rule2 = (P"c" + P"d")^0
}

lpeg.match(Ct(P(p)), parsestring)

What is important is the type of pattern matching function, the way they are combined(the operators), and the grammar itself.

(See LPeg docs for complete descriptions)

  • P - Creates a pattern from strings that matches that string exactly
  • V - Creates a logical reference to rule. Used to use a rule as a pattern in another rule
  • C - Creates a capture point. When the parser has make a match up to this point it will stick the result into a table
  • Ct - Creates a capture table. A capture table holds all the sub captures(using C) inside it. You can create nested tables this way and then parse them afterwards.

  • '*' - Combines patterns sequentially. Rule1 in the example will match only the string "ab"

  • '+' - Allows either or pattern. Rule 2 will match the strings "c" or "d" or nothing(due to the ^0). It is is "ordered" in that it will return a match as soon as it happens as it checks from the first to the last pattern. So if we have P"a" + P"ab" we will get "a" on the string "ab" since P"a" matches the first "a".
  • '-' - Prevents matching. patt1 - patt2 will first try to match patt2 in the string. If this fails then it will try to match patt1 and return the match if patt1 is there. If patt2 was matched THEN the whole pattern fails. e.g., "a" - "ba" will fail on "ba", "baa", "badfe" but succed on "a", "aba", "aaa" since "ba" is not matched at the start.
  • '^' - Allows repetition of the rule. ^0 will try to match the rule as much as possible but at most 0 times.

There are many more lpeg functions and operators along with "repetition" control (using the ^ operator).

The basic idea is to simply setup the lpeg grammar table then match it. To create the grammar table you need to represent your grammar using lpeg's pattern matching constructs. To be able to do useful stuff with it you'll need to use the capturing functions to capture data or apply functions to the matches.

The grammar in the example will match the strings ab, abc, abd, abcadsfd, abd2f$F3, etc. The reason it will match anything after ab/abc/abd is because we didn't give the start rule a stop condition which can be represented by -1 for end of line.

Here are some useful links:

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.